

<!DOCTYPE html>
<html lang="zh-CN" data-default-color-scheme=&#34;auto&#34;>



<head>
  <meta charset="UTF-8">
  <link rel="apple-touch-icon" sizes="76x76" href="/img/favicon.ico">
  <link rel="icon" href="/img/favicon.ico">
  <meta name="viewport"
        content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, shrink-to-fit=no">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  
  <meta name="theme-color" content="#2f4154">
  <meta name="description" content="叶尘的技术升级小木屋">
  <meta name="author" content="叶尘">
  <meta name="keywords" content="">
  
  <title>MyBatis学习 - 叶尘的技术升级小木屋</title>

  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css" />


  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/github-markdown-css@4.0.0/github-markdown.min.css" />
  <link  rel="stylesheet" href="/lib/hint/hint.min.css" />

  
    
    
      
      <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/highlight.js@10.7.2/styles/github-gist.min.css" />
    
  

  
    <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.css" />
  



<!-- 主题依赖的图标库，不要自行修改 -->

<link rel="stylesheet" href="//at.alicdn.com/t/font_1749284_ba1fz6golrf.css">



<link rel="stylesheet" href="//at.alicdn.com/t/font_1736178_kmeydafke9r.css">


<link  rel="stylesheet" href="/css/main.css" />

<!-- 自定义样式保持在最底部 -->

  
<link rel="stylesheet" href="//cdn.jsdelivr.net/gh/bynotes/texiao/source/css/shubiao.css">
<link rel="stylesheet" href="//cdn.jsdelivr.net/gh/bynotes/texiao/source/css/gundongtiao.css">
<link rel="stylesheet" href="//cdn.jsdelivr.net/gh/bynotes/texiao/source/css/daziyanse.css">
<link rel="stylesheet" href="//cdn.jsdelivr.net/gh/bynotes/texiao/source/css/toubudaziji.css">
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.css">



  <script id="fluid-configs">
    var Fluid = window.Fluid || {};
    var CONFIG = {"hostname":"www.yechen-blog.cn","root":"/","version":"1.8.11","typing":{"enable":true,"typeSpeed":70,"cursorChar":"_","loop":false},"anchorjs":{"enable":true,"element":"h1,h2,h3,h4,h5,h6","placement":"right","visible":"hover","icon":""},"progressbar":{"enable":true,"height_px":3,"color":"#29d","options":{"showSpinner":false,"trickleSpeed":100}},"copy_btn":true,"image_zoom":{"enable":true,"img_url_replace":["",""]},"toc":{"enable":true,"headingSelector":"h1,h2,h3,h4,h5,h6","collapseDepth":0},"lazyload":{"enable":true,"loading_img":"/img/loading.gif","onlypost":false,"offset_factor":2},"web_analytics":{"enable":false,"baidu":null,"google":null,"gtag":null,"tencent":{"sid":null,"cid":null},"woyaola":null,"cnzz":null,"leancloud":{"app_id":null,"app_key":null,"server_url":null}},"search_path":"/local-search.xml"};
  </script>
  <script  src="/js/utils.js" ></script>
  <script  src="/js/color-schema.js" ></script>
<meta name="generator" content="Hexo 5.4.0"></head>


<body>
  <header style="height: 70vh;">
    <nav id="navbar" class="navbar fixed-top  navbar-expand-lg navbar-dark scrolling-navbar">
  <div class="container">
    <a class="navbar-brand"
       href="/">&nbsp;<strong>YECHEN</strong>&nbsp;</a>

    <button id="navbar-toggler-btn" class="navbar-toggler" type="button" data-toggle="collapse"
            data-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <div class="animated-icon"><span></span><span></span><span></span></div>
    </button>

    <!-- Collapsible content -->
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav ml-auto text-center">
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/">
                <i class="iconfont icon-home-fill"></i>
                首页
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/categories/">
                <i class="iconfont icon-qrcode"></i>
                分类
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/tags/">
                <i class="iconfont icon-tags-fill"></i>
                标签
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/about/">
                <i class="iconfont icon-user-fill"></i>
                关于
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/playlist/">
                <i class="iconfont icon-music"></i>
                音乐
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item dropdown">
              <a class="nav-link dropdown-toggle" target="_self" role="button"
                 data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                <i class="iconfont icon-books"></i>
                链接
              </a>
              <div class="dropdown-menu" aria-labelledby="navbarDropdown">
                
                  
                  
                  
                  <a class="dropdown-item" target="_blank" rel="noopener" href="https://hexo.fluid-dev.com/">
                    
                    主题博客
                  </a>
                
                  
                  
                  
                  <a class="dropdown-item" target="_blank" rel="noopener" href="https://hexo.fluid-dev.com/docs/guide/">
                    
                    配置指南
                  </a>
                
                  
                  
                  
                  <a class="dropdown-item" target="_blank" rel="noopener" href="https://hexo.fluid-dev.com/docs/icon/">
                    
                    图标用法
                  </a>
                
                  
                  
                  
                  <a class="dropdown-item" target="_blank" rel="noopener" href="https://www.bilibili.com">
                    
                    哔哩哔哩
                  </a>
                
              </div>
            </li>
          
        
        
          <li class="nav-item" id="search-btn">
            <a class="nav-link" target="_self" data-toggle="modal" data-target="#modalSearch">&nbsp;<i
                class="iconfont icon-search"></i>&nbsp;</a>
          </li>
        
        
          <li class="nav-item" id="color-toggle-btn">
            <a class="nav-link" target="_self">&nbsp;<i
                class="iconfont icon-dark" id="color-toggle-icon"></i>&nbsp;</a>
          </li>
        
      </ul>
    </div>
  </div>
</nav>

    <div class="banner" id="banner" parallax=true
         style="background: url('/img/banner.jpg') no-repeat center center;
           background-size: cover;">
      <div class="full-bg-img">
        <div class="mask flex-center" style="background-color: rgba(0, 0, 0, 0.3)">
          <div class="page-header text-center fade-in-up">
            <span class="h2" id="subtitle" title="MyBatis学习">
              
            </span>

            
              <div class="mt-3">
  
    <span class="post-meta mr-2">
      <i class="iconfont icon-author" aria-hidden="true"></i>
      叶尘
    </span>
  
  
    <span class="post-meta">
      <i class="iconfont icon-date-fill" aria-hidden="true"></i>
      <time datetime="2021-10-30 13:26" pubdate>
        星期六, 十月 30日 2021, 1:26 下午
      </time>
    </span>
  
</div>

<div class="mt-1">
  
    
    <span class="post-meta mr-2">
      <i class="iconfont icon-chart"></i>
      13.4k 字
    </span>
  

  
    
    <span class="post-meta mr-2">
      <i class="iconfont icon-clock-fill"></i>
      
      
      197
       分钟
    </span>
  

  
  
    
      <!-- LeanCloud 统计文章PV -->
      <span id="leancloud-page-views-container" class="post-meta" style="display: none">
        <i class="iconfont icon-eye" aria-hidden="true"></i>
        <span id="leancloud-page-views"></span> 次
      </span>
    
  
</div>

            
          </div>

          
        </div>
      </div>
    </div>
  </header>

  <main>
    
      

<div class="container-fluid nopadding-x">
  <div class="row nomargin-x">
    <div class="d-none d-lg-block col-lg-2"></div>
    <div class="col-lg-8 nopadding-x-md">
      <div class="container nopadding-x-md" id="board-ctn">
        <div class="py-5" id="board">
          <article class="post-content mx-auto">
            <!-- SEO header -->
            <h1 style="display: none">MyBatis学习</h1>
            
            <div class="markdown-body">
              <h2 id="一、三层架构"><a href="#一、三层架构" class="headerlink" title="一、三层架构"></a>一、三层架构</h2><blockquote>
<p>界面层（视图层）</p>
</blockquote>
<p>完成和用户的交互，接受请求，显示请求的处理结果。</p>
<p>使用 <code>SpringMVC</code> 框架来实现。</p>
<blockquote>
<p>业务逻辑层</p>
</blockquote>
<p>计算数据，处理业务逻辑。</p>
<p>使用 <code>Spring</code> 框架来实现。</p>
<blockquote>
<p>数据访问层（持久层）</p>
</blockquote>
<p>对数据库进行操作。</p>
<p>使用 <code>MyBatis</code> 进行操作。</p>
<h2 id="二、概述"><a href="#二、概述" class="headerlink" title="二、概述"></a>二、概述</h2><h3 id="1-MyBatis-介绍"><a href="#1-MyBatis-介绍" class="headerlink" title="1. MyBatis 介绍"></a>1. MyBatis 介绍</h3><p>它是一款<strong>半自动</strong>的 <code>ORM</code> 持久层框架，具有较高的 SQL 灵活性，支持高级映射 (一对一，一对多)，动态 SQL，延迟加载和缓存等特性，但它的数据库无关性较低。</p>
<ul>
<li><p>什么是 <code>ORM</code>：</p>
<p><code>Object Relation Mapping</code>，对象关系映射。<strong>对象指的是 Java 对象，关系指的是数据库中的关系模型</strong>，对象关系映射，指的就是在 <strong>Java 对象和数据库的关系模型之间建立一种对应关系</strong>，比如用一个Java的Student类，去对应数据库中的一张 student 表，类中的属性和表中的列一一对应。Student类就对应student表，一个Student对象就对应student表中的一行数据。</p>
</li>
<li><p>为什么 mybatis 是<strong>半自动</strong>的 ORM 框架：</p>
<p><strong>用 mybatis 进行开发，需要手动编写 SQL 语句</strong>。而全自动的 ORM 框架，如 <code>hibernate</code>，则不需要编写 SQL 语句。用 hibernate 开发，只需要定义好 ORM 映射关系，就可以直接进行 CRUD 操作了。由于 mybatis 需要手写SQL 语句，<strong>所以它有较高的灵活性，可以根据需要，自由地对 SQL 进行定制</strong>，也因为要手写 SQL，<strong>当要切换数据库时，SQL 语句可能就要重写，因为不同的数据库有不同的方言 (Dialect)，所以 mybatis 的数据库无关性低</strong>。虽然 mybatis 需要手写 SQL，但相比 JDBC，它提供了输入映射和输出映射，可以很方便地进行 SQL 参数设置，以及结果集封装。并且还提供了关联查询和动态 SQL 等功能，极大地提升了开发的效率。并且它的学习成本也比 hibernate 低很多。</p>
</li>
</ul>
<h3 id="2-简单使用-MyBatis"><a href="#2-简单使用-MyBatis" class="headerlink" title="2. 简单使用 MyBatis"></a>2. 简单使用 MyBatis</h3><p>参照<a target="_blank" rel="noopener" href="https://mybatis.org/mybatis-3/zh/getting-started.html">官网</a></p>
<h4 id="创建数据库和数据表"><a href="#创建数据库和数据表" class="headerlink" title="创建数据库和数据表"></a>创建数据库和数据表</h4><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-keyword">CREATE</span> DATABASE mybatis;<br>use mybatis;<br><br><span class="hljs-keyword">DROP</span> <span class="hljs-keyword">TABLE</span> IF <span class="hljs-keyword">EXISTS</span> `student`;<br><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> `student`  (<br>  `id` <span class="hljs-type">int</span>(<span class="hljs-number">0</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> AUTO_INCREMENT,<br>  `stu_name` <span class="hljs-type">varchar</span>(<span class="hljs-number">255</span>) <span class="hljs-type">CHARACTER</span> <span class="hljs-keyword">SET</span> utf8 <span class="hljs-keyword">COLLATE</span> utf8_general_ci <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-keyword">NULL</span>,<br>  `email` <span class="hljs-type">varchar</span>(<span class="hljs-number">255</span>) <span class="hljs-type">CHARACTER</span> <span class="hljs-keyword">SET</span> utf8 <span class="hljs-keyword">COLLATE</span> utf8_general_ci <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-keyword">NULL</span>,<br>  `age` <span class="hljs-type">int</span>(<span class="hljs-number">0</span>) <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-keyword">NULL</span>,<br>  <span class="hljs-keyword">PRIMARY</span> KEY (`id`) <span class="hljs-keyword">USING</span> BTREE<br>) ENGINE <span class="hljs-operator">=</span> InnoDB <span class="hljs-type">CHARACTER</span> <span class="hljs-keyword">SET</span> <span class="hljs-operator">=</span> utf8 <span class="hljs-keyword">COLLATE</span> <span class="hljs-operator">=</span> utf8_general_ci ROW_FORMAT <span class="hljs-operator">=</span> <span class="hljs-keyword">Dynamic</span>;<br><br><span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> `student` <span class="hljs-keyword">VALUES</span> (<span class="hljs-number">1</span>, <span class="hljs-string">&#x27;zhagnsan&#x27;</span>, <span class="hljs-string">&#x27;zhangsan@qq.com&#x27;</span>, <span class="hljs-number">20</span>);<br><span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> `student` <span class="hljs-keyword">VALUES</span> (<span class="hljs-number">2</span>, <span class="hljs-string">&#x27;lisi&#x27;</span>, <span class="hljs-string">&#x27;lisi@qq.com&#x27;</span>, <span class="hljs-number">21</span>);<br><span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> `student` <span class="hljs-keyword">VALUES</span> (<span class="hljs-number">3</span>, <span class="hljs-string">&#x27;wangwu&#x27;</span>, <span class="hljs-string">&#x27;wangwu@qq.com&#x27;</span>, <span class="hljs-number">22</span>);<br><span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> `student` <span class="hljs-keyword">VALUES</span> (<span class="hljs-number">4</span>, <span class="hljs-string">&#x27;zhaoliu&#x27;</span>, <span class="hljs-string">&#x27;zhaoliu@qq.com&#x27;</span>, <span class="hljs-number">23</span>);<br></code></pre></td></tr></table></figure>

<h4 id="创建-maven-工程"><a href="#创建-maven-工程" class="headerlink" title="创建 maven 工程"></a>创建 maven 工程</h4><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">dependencies</span>&gt;</span><br>    <span class="hljs-comment">&lt;!-- mybatis 依赖 --&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.mybatis<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>mybatis<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>3.5.7<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br><br>    <span class="hljs-comment">&lt;!-- mysql 驱动 --&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>mysql<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>mysql-connector-java<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>8.0.26<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br><br>    <span class="hljs-comment">&lt;!-- 单元测试依赖 --&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>junit<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>junit<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>4.13.2<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">scope</span>&gt;</span>test<span class="hljs-tag">&lt;/<span class="hljs-name">scope</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br>    <br>    <span class="hljs-comment">&lt;!-- lombok --&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.projectlombok<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>lombok<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>1.18.20<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">dependencies</span>&gt;</span><br></code></pre></td></tr></table></figure>

<h4 id="创建-mybatis-核心配置文件"><a href="#创建-mybatis-核心配置文件" class="headerlink" title="创建 mybatis 核心配置文件"></a>创建 mybatis 核心配置文件</h4><p>mybatis-config.xml</p>
<p>放在 resource 目录下，即类路径下，在其中主要指定<strong>数据源信息</strong> 和 <strong>映射文件信息</strong></p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-meta">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; ?&gt;</span><br><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">configuration</span></span><br><span class="hljs-meta">        <span class="hljs-meta-keyword">PUBLIC</span> <span class="hljs-meta-string">&quot;-//mybatis.org//DTD Config 3.0//EN&quot;</span></span><br><span class="hljs-meta">        <span class="hljs-meta-string">&quot;http://mybatis.org/dtd/mybatis-3-config.dtd&quot;</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">configuration</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">environments</span> <span class="hljs-attr">default</span>=<span class="hljs-string">&quot;development&quot;</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">environment</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;development&quot;</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">transactionManager</span> <span class="hljs-attr">type</span>=<span class="hljs-string">&quot;JDBC&quot;</span>/&gt;</span><br>            <span class="hljs-comment">&lt;!-- 指定数据源信息 --&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">dataSource</span> <span class="hljs-attr">type</span>=<span class="hljs-string">&quot;POOLED&quot;</span>&gt;</span><br>                <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;driver&quot;</span> <span class="hljs-attr">value</span>=<span class="hljs-string">&quot;com.mysql.cj.jdbc.Driver&quot;</span>/&gt;</span><br>                <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;url&quot;</span> <span class="hljs-attr">value</span>=<span class="hljs-string">&quot;jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC<span class="hljs-symbol">&amp;amp;</span>characterEncoding=utf8<span class="hljs-symbol">&amp;amp;</span>useUnicode=true<span class="hljs-symbol">&amp;amp;</span>useSSL=false&quot;</span>/&gt;</span><br>                <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;username&quot;</span> <span class="hljs-attr">value</span>=<span class="hljs-string">&quot;root&quot;</span>/&gt;</span><br>                <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;password&quot;</span> <span class="hljs-attr">value</span>=<span class="hljs-string">&quot;123456&quot;</span>/&gt;</span><br>            <span class="hljs-tag">&lt;/<span class="hljs-name">dataSource</span>&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">environment</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">environments</span>&gt;</span><br>    <span class="hljs-comment">&lt;!-- 指定映射文件 --&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">mappers</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">mapper</span> <span class="hljs-attr">resource</span>=<span class="hljs-string">&quot;StudentMapper.xml&quot;</span>/&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">mappers</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">configuration</span>&gt;</span><br><br></code></pre></td></tr></table></figure>

<h4 id="创建实体类-Student"><a href="#创建实体类-Student" class="headerlink" title="创建实体类 Student"></a>创建实体类 Student</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Data</span><br><span class="hljs-meta">@NoArgsConstructor</span><br><span class="hljs-meta">@AllArgsConstructor</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Student</span> </span>&#123;<br>    <span class="hljs-keyword">private</span> Integer id;<br>    <span class="hljs-keyword">private</span> String stuName;<br>    <span class="hljs-keyword">private</span> String email;<br>    <span class="hljs-keyword">private</span> Integer age;<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="创建-sql-映射文件"><a href="#创建-sql-映射文件" class="headerlink" title="创建 sql 映射文件"></a>创建 sql 映射文件</h4><p>StudentMapper.xml</p>
<p>放在 resource 目录下，即类路径下</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs java">&lt;?xml version=<span class="hljs-string">&quot;1.0&quot;</span> encoding=<span class="hljs-string">&quot;UTF-8&quot;</span> ?&gt;<br>&lt;!DOCTYPE mapper<br>        PUBLIC <span class="hljs-string">&quot;-//mybatis.org//DTD Mapper 3.0//EN&quot;</span><br>        <span class="hljs-string">&quot;http://mybatis.org/dtd/mybatis-3-mapper.dtd&quot;</span>&gt;<br><br>&lt;mapper namespace=<span class="hljs-string">&quot;cn.yechen.mapper.StudentMapper&quot;</span>&gt;<br>    &lt;select id=<span class="hljs-string">&quot;selectOne&quot;</span> resultType=<span class="hljs-string">&quot;cn.yechen.bean.Student&quot;</span>&gt;<br>        select * from student where id=#&#123;id&#125;<br>    &lt;/select&gt;<br>&lt;/mapper&gt;<br></code></pre></td></tr></table></figure>

<h4 id="测试类中测试"><a href="#测试类中测试" class="headerlink" title="测试类中测试"></a>测试类中测试</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Test</span><br><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">testSelectStudent</span><span class="hljs-params">()</span> </span>&#123;<br>    <span class="hljs-comment">// 1. 定义 mybatis 主配置文件的名称，从类路径开始</span><br>    String resource = <span class="hljs-string">&quot;mybatis-config.xml&quot;</span>;<br><br>    <span class="hljs-comment">// 2. 读取主配置文件</span><br>    InputStream inputStream = <span class="hljs-keyword">null</span>;<br>    <span class="hljs-keyword">try</span> &#123;<br>        inputStream = Resources.getResourceAsStream(resource);<br>    &#125; <span class="hljs-keyword">catch</span> (IOException e) &#123;<br>        e.printStackTrace();<br>    &#125;<br><br>    <span class="hljs-comment">// 3. 通过 SqlSessionFactoryBuilder 对象的 build() 方法创建 SqlSessionFactory 对象</span><br>    SqlSessionFactory sqlSessionFactory = <span class="hljs-keyword">new</span> SqlSessionFactoryBuilder().build(inputStream);<br><br>    <span class="hljs-comment">// 4. 从 SqlSessionFactory 对象中获取 SqlSession 独享</span><br>    SqlSession sqlSession = sqlSessionFactory.openSession();<br><br>    <span class="hljs-comment">// 5。 指定要执行的 sql 语句的标识（即之前 sql 映射文件中的 namespace + sql语句的id）</span><br>    String sqlId = <span class="hljs-string">&quot;cn.yechen.mapper.StudentMapper.selectOne&quot;</span>;<br><br>    <span class="hljs-comment">// 6。 通过 sqlId 执行 sql</span><br>    Student student = sqlSession.selectOne(sqlId, <span class="hljs-number">1</span>);<br><br>    <span class="hljs-comment">// 7. 输出结果</span><br>    System.out.println(student);<br><br>    <span class="hljs-comment">// 8. 关闭 SqlSession 对象</span><br>    sqlSession.close();<br>&#125;<br></code></pre></td></tr></table></figure>

<p>此时的测试结果：</p>
<p><img src="https://yechen-blog-image.oss-cn-hangzhou.aliyuncs.com/images/image-20211018130129662.png" srcset="/img/loading.gif" lazyload alt="测试结果"></p>
<p><strong>原因分析：</strong></p>
<p>数据库中字段名为 stu_name，实体类中字段名为 stuName，在查询的时候就不能对上了，因此可以在查询的时候为<strong>字段取别名</strong>（当然之后还有其他方法）</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">select</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;selectOne&quot;</span> <span class="hljs-attr">resultType</span>=<span class="hljs-string">&quot;cn.yechen.bean.Student&quot;</span>&gt;</span><br>    select id, stu_name as stuName, email, age from student where id=#&#123;id&#125;<br><span class="hljs-tag">&lt;/<span class="hljs-name">select</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p>再次测试：</p>
<p><img src="https://yechen-blog-image.oss-cn-hangzhou.aliyuncs.com/images/image-20211018130401722.png" srcset="/img/loading.gif" lazyload alt="测试结果"></p>
<h3 id="3-分析主要类"><a href="#3-分析主要类" class="headerlink" title="3. 分析主要类"></a>3. 分析主要类</h3><p><code>Resources</code>：mybatis 中的一个类，<strong>负责读取主配置文件</strong>。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs java">InputStream inputStream = Resources.getResourceAsStream(<span class="hljs-string">&quot;mybatis-config.xml&quot;</span>);<br></code></pre></td></tr></table></figure>

<p><code>SqlSessionFactoryBuilder</code>：只有一个功能：<strong>用于创建 SqlSessionFactory 对象</strong>。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs java">SqlSessionFactory factory = <span class="hljs-keyword">new</span> SqlSessionFactoryBuilder.build(inputStream);<br></code></pre></td></tr></table></figure>

<p><code>SqlSessionFactory（接口）</code>：<strong>重量级对象</strong>，该对象在创建时耗时长、使用资源多，在整个项目中，有一个就够用了。作用：<strong>获取 SqlSession 对象</strong>。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs java">SqlSession sqlSession = factory.openSession();<br></code></pre></td></tr></table></figure>

<ul>
<li>SqlSessionFactory 的默认实现类是 DefaultSqlSessionFactory</li>
<li>方法 <code>openSession</code>：<ul>
<li>openSession() 无参：获取的是<strong>非自动提交事务</strong>的 SqlSession 对象。</li>
<li>openSession(boolean autoCommit)：<strong>自己设置是否自动提交事务（true 表示自动提交）</strong>，并获得对应的 SqlSession 对象</li>
</ul>
</li>
</ul>
<p><code>SqlSession（接口）</code>：定义了操作数据库的方法，增删改查，事务提交，事务回滚。</p>
<ul>
<li>SqlSession 的默认实现类是 DefaultSqlSession</li>
<li>SqlSession 对象<strong>不是线程安全的</strong>，在执行完 sql 语句后，要使用 <strong>.close() 方法关闭</strong>它。</li>
</ul>
<h3 id="4-使用-MyBatis-的动态代理"><a href="#4-使用-MyBatis-的动态代理" class="headerlink" title="4. 使用 MyBatis 的动态代理"></a>4. 使用 MyBatis 的动态代理</h3><p>mybatis 通过 SqlSession 的方法动态帮你创建 dao 接口的实现类，通过实现类来执行 sql。</p>
<ol>
<li><p>封装工具类，通过工具类获取 SqlSession 对象</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyBatisUtils</span> </span>&#123;<br><br>    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> SqlSessionFactory factory;<br><br>    <span class="hljs-comment">// SqlSessionFactory 对象在程序中只需要一个，因此将创建的代码写在静态代码块中，只在类加载的时候创建一次</span><br>    <span class="hljs-keyword">static</span> &#123;<br>        <span class="hljs-comment">// 读取主配置文件</span><br>        String rescourse = <span class="hljs-string">&quot;mybatis-config.xml&quot;</span>;<br>        InputStream inputStream = <span class="hljs-keyword">null</span>;<br>        <span class="hljs-keyword">try</span> &#123;<br>            inputStream = Resources.getResourceAsStream(rescourse);<br>        &#125; <span class="hljs-keyword">catch</span> (IOException e) &#123;<br>            e.printStackTrace();<br>        &#125;<br>        <span class="hljs-comment">// 创建 SqlSessionFactory 对象</span><br>        factory = <span class="hljs-keyword">new</span> SqlSessionFactoryBuilder().build(inputStream);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 获取 SqlSession 对象</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span> SqlSession 对象</span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> SqlSession <span class="hljs-title">getSqlSession</span><span class="hljs-params">()</span> </span>&#123;<br>        SqlSession sqlSession = <span class="hljs-keyword">null</span>;<br>        <span class="hljs-keyword">if</span> (factory != <span class="hljs-keyword">null</span>) &#123;<br>            sqlSession = factory.openSession();<br>        &#125;<br>        <span class="hljs-keyword">return</span> sqlSession;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure></li>
<li><p>创建 mapper 接口类</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">StudentMapper</span> </span>&#123;<br>    <span class="hljs-function">Student <span class="hljs-title">selectOne</span><span class="hljs-params">(Integer id)</span></span>;<br>&#125;<br></code></pre></td></tr></table></figure></li>
<li><p>sql 映射文件（<strong>namespace 一定要是 mapper 接口类的全限定名，sql 语句的 id 一定要是方法名</strong>）</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-meta">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; ?&gt;</span><br><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">mapper</span></span><br><span class="hljs-meta">        <span class="hljs-meta-keyword">PUBLIC</span> <span class="hljs-meta-string">&quot;-//mybatis.org//DTD Mapper 3.0//EN&quot;</span></span><br><span class="hljs-meta">        <span class="hljs-meta-string">&quot;http://mybatis.org/dtd/mybatis-3-mapper.dtd&quot;</span>&gt;</span><br><br><span class="hljs-tag">&lt;<span class="hljs-name">mapper</span> <span class="hljs-attr">namespace</span>=<span class="hljs-string">&quot;cn.yechen.mapper.StudentMapper&quot;</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">select</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;selectOne&quot;</span> <span class="hljs-attr">resultType</span>=<span class="hljs-string">&quot;cn.yechen.bean.Student&quot;</span>&gt;</span><br>        select * from student where id=#&#123;id&#125;<br>    <span class="hljs-tag">&lt;/<span class="hljs-name">select</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">mapper</span>&gt;</span><br></code></pre></td></tr></table></figure></li>
<li><p>测试</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Test</span><br><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">test</span><span class="hljs-params">()</span> </span>&#123;<br>    SqlSession sqlSession = MyBatisUtils.getSqlSession();<br>    <span class="hljs-comment">// 通过 getMapper() 方法获取 StudentMapper 接口的动态代理实现类</span><br>    StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);<br>   	 <span class="hljs-comment">// 打印 studentMapper 对象，查看其具体实现类</span><br>    System.out.println(<span class="hljs-string">&quot;studentMapper --&gt;&quot;</span> + studentMapper.getClass());<br>    Student student = studentMapper.selectOne(<span class="hljs-number">1</span>);<br>    System.out.println(student);<br>&#125;<br></code></pre></td></tr></table></figure>

<p><img src="https://yechen-blog-image.oss-cn-hangzhou.aliyuncs.com/images/image-20211018201550472.png" srcset="/img/loading.gif" lazyload alt="测试结果"></p>
</li>
</ol>
<h2 id="三、MyBatis-全局配置文件"><a href="#三、MyBatis-全局配置文件" class="headerlink" title="三、MyBatis 全局配置文件"></a>三、MyBatis 全局配置文件</h2><p><a target="_blank" rel="noopener" href="https://mybatis.org/mybatis-3/zh/configuration.html">官方教程</a></p>
<h3 id="1-properties（属性"><a href="#1-properties（属性" class="headerlink" title="1. properties（属性)"></a>1. properties（属性)</h3><p>这些属性可以在外部进行配置，并可以进行动态替换。</p>
<p>例如数据库连接信息，可以单独提出形成一个 <strong>db.properties 文件</strong></p>
<figure class="highlight properties"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs properties"><span class="hljs-meta">jdbc.driver</span>=<span class="hljs-string">com.mysql.cj.jdbc.Driver</span><br><span class="hljs-meta">jdbc.url</span>=<span class="hljs-string">jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&amp;characterEncoding=utf8&amp;useUnicode=true&amp;useSSL=false</span><br><span class="hljs-meta">jdbc.username</span>=<span class="hljs-string">root</span><br><span class="hljs-meta">jdbc.password</span>=<span class="hljs-string">123456</span><br></code></pre></td></tr></table></figure>

<p>接下来在主配置文件中就可以引入这个文件，并在数据源配置中动态引用数据</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">configuration</span>&gt;</span><br>	 <span class="hljs-comment">&lt;!-- 指定配置文件位置，这里在类路径下，直接写 --&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">properties</span> <span class="hljs-attr">resource</span>=<span class="hljs-string">&quot;db.properties&quot;</span>/&gt;</span><br><br>    <span class="hljs-tag">&lt;<span class="hljs-name">environments</span> <span class="hljs-attr">default</span>=<span class="hljs-string">&quot;development&quot;</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">environment</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;development&quot;</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">transactionManager</span> <span class="hljs-attr">type</span>=<span class="hljs-string">&quot;JDBC&quot;</span>/&gt;</span><br>            <span class="hljs-comment">&lt;!-- 动态指定数据源信息 --&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">dataSource</span> <span class="hljs-attr">type</span>=<span class="hljs-string">&quot;POOLED&quot;</span>&gt;</span><br>                <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;driver&quot;</span> <span class="hljs-attr">value</span>=<span class="hljs-string">&quot;$&#123;jdbc.driver&#125;&quot;</span>/&gt;</span><br>                <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;url&quot;</span> <span class="hljs-attr">value</span>=<span class="hljs-string">&quot;$&#123;jdbc.url&#125;&quot;</span>/&gt;</span><br>                <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;username&quot;</span> <span class="hljs-attr">value</span>=<span class="hljs-string">&quot;$&#123;jdbc.username&#125;&quot;</span>/&gt;</span><br>                <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;password&quot;</span> <span class="hljs-attr">value</span>=<span class="hljs-string">&quot;$&#123;jdbc.password&#125;&quot;</span>/&gt;</span><br>            <span class="hljs-tag">&lt;/<span class="hljs-name">dataSource</span>&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">environment</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">environments</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">configuration</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p>当然在 <code>&lt;properties&gt;&lt;/properties&gt;</code> <strong>标签中</strong>也是可以写值的，如：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">properties</span> <span class="hljs-attr">resource</span>=<span class="hljs-string">&quot;db.properties&quot;</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;username&quot;</span> <span class="hljs-attr">value</span>=<span class="hljs-string">&quot;yechen&quot;</span>/&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;password&quot;</span> <span class="hljs-attr">value</span>=<span class="hljs-string">&quot;123&quot;</span>/&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">properties</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p>同时在创建 sqlSessionFactory 对象是，在 build() <strong>方法中</strong>也可以传递进去属性数据</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs java">SqlSessionFactory factory = <span class="hljs-keyword">new</span> SqlSessionFactoryBuilder().build(reader, props);<br><br><span class="hljs-comment">// ... 或者 ...</span><br><br>SqlSessionFactory factory = <span class="hljs-keyword">new</span> SqlSessionFactoryBuilder().build(reader, environment, props);<br></code></pre></td></tr></table></figure>

<p><strong>读取配置数据的顺序：</strong></p>
<ol>
<li>先读取 <code>&lt;properties&gt;&lt;/properties&gt;</code> 标签中指定的值（<strong>优先级最低</strong>）</li>
<li>再读取标签中 resource 或 url 指定的文件中的值，并覆盖之前已经赋好的值（<strong>优先级较高</strong>）</li>
<li>最后读取作为方法参数传递的属性，并覆盖之前读取过的同名属性（<strong>优先级最高</strong>）</li>
</ol>
<p>MyBatis 3.4.2 开始，可以为占位符指定一个<strong>默认值</strong></p>
<p>这个特性默认是关闭的，要先开启这个特性：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">properties</span> <span class="hljs-attr">resource</span>=<span class="hljs-string">&quot;db.properties&quot;</span>&gt;</span><br>    <span class="hljs-comment">&lt;!-- 启用默认值特性 --&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;org.apache.ibatis.parsing.PropertyParser.enable-default-value&quot;</span> <span class="hljs-attr">value</span>=<span class="hljs-string">&quot;true&quot;</span>/&gt;</span> <br><span class="hljs-tag">&lt;/<span class="hljs-name">properties</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p>在引用值的时候就可以指定默认值</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">dataSource</span> <span class="hljs-attr">type</span>=<span class="hljs-string">&quot;POOLED&quot;</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;username&quot;</span> <span class="hljs-attr">value</span>=<span class="hljs-string">&quot;$&#123;jdbc.username:root&#125;&quot;</span>/&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;password&quot;</span> <span class="hljs-attr">value</span>=<span class="hljs-string">&quot;$&#123;jdbc.password:123456&#125;&quot;</span>/&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">dataSource</span>&gt;</span><br></code></pre></td></tr></table></figure>



<h3 id="2-settings（设置）"><a href="#2-settings（设置）" class="headerlink" title="2. settings（设置）"></a>2. settings（设置）</h3><p>MyBatis 中极为重要的调整设置，它们会改变 MyBatis 的运行时行为。</p>
<p><a target="_blank" rel="noopener" href="https://mybatis.org/mybatis-3/zh/configuration.html#settings">官方列举的设置列表</a></p>
<p><img src="https://yechen-blog-image.oss-cn-hangzhou.aliyuncs.com/images/image-20211018204654203.png" srcset="/img/loading.gif" lazyload alt="常用设置"></p>
<p>之前我在查询数据库的时候，由于数据库中的字段名称为 stu_name，而实体类中是 stuName，这样导致我们在写 sql 语句的时候要为查询到的数据设置别名才能最后封装到实体类中，现在使用 <code>mapUnderscoreToCamelCase</code> 这个设置，开启<strong>自动驼峰命名规则映射</strong>，这样查询时 <strong>stu_name 就可以直接映射为 stuName 了</strong></p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-comment">&lt;!-- 设置 --&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">settings</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">setting</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;mapUnderscoreToCamelCase&quot;</span> <span class="hljs-attr">value</span>=<span class="hljs-string">&quot;true&quot;</span>/&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">settings</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p>在 sql 语句中就可以不设置别名了</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">mapper</span> <span class="hljs-attr">namespace</span>=<span class="hljs-string">&quot;cn.yechen.mapper.StudentMapper&quot;</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">select</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;selectOne&quot;</span> <span class="hljs-attr">resultType</span>=<span class="hljs-string">&quot;cn.yechen.bean.Student&quot;</span>&gt;</span><br>        select * from student where id=#&#123;id&#125;<br>    <span class="hljs-tag">&lt;/<span class="hljs-name">select</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">mapper</span>&gt;</span><br></code></pre></td></tr></table></figure>



<h3 id="3-typeAliases（类型别名）"><a href="#3-typeAliases（类型别名）" class="headerlink" title="3. typeAliases（类型别名）"></a>3. typeAliases（类型别名）</h3><p>类型别名可以为 Java 类型设置一个简单的别名，便于之后应用这个 Java 类型</p>
<p>有两种指定别名的方法</p>
<p><strong>方法一：</strong><code>typeAlias</code> 标签，<code>alias</code> 属性写别名，<code>type</code> 属性填类全限定类名</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">typeAliases</span>&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">typeAlias</span> <span class="hljs-attr">alias</span>=<span class="hljs-string">&quot;Author&quot;</span> <span class="hljs-attr">type</span>=<span class="hljs-string">&quot;domain.blog.Author&quot;</span>/&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">typeAliases</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p>alias 这个属性可以不写，那么<strong>默认就是类名，不区分大小写</strong></p>
<p>这个方法需要一个类一个类指定，有的不方便</p>
<p><strong>方法二：</strong><code>package</code> 标签，<code>name</code> 属性指定包的名称，为这个包下的所有类批量起默认别名（<strong>类名，不关注大小写</strong>）</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">typeAliases</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">package</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;cn.yechen.bean&quot;</span>/&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">typeAliases</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p>但是当指定多个 package 时，不同的包中有可能存在同名的类，这个时候就需要使用注解 <code>@Alias(&quot;自定义别名&quot;)</code> 在类上，指定的名称<strong>同样不分大小写</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Alias(&quot;s&quot;)</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Student</span> </span>&#123;<br>&#125;<br></code></pre></td></tr></table></figure>

<p>mybatis 官方为常用的一些 Java 类都已经起好了别名</p>
<table>
<thead>
<tr>
<th align="center">别名</th>
<th align="center">映射的类型</th>
</tr>
</thead>
<tbody><tr>
<td align="center">_byte</td>
<td align="center">byte</td>
</tr>
<tr>
<td align="center">_long</td>
<td align="center">long</td>
</tr>
<tr>
<td align="center">_short</td>
<td align="center">short</td>
</tr>
<tr>
<td align="center">_int</td>
<td align="center">int</td>
</tr>
<tr>
<td align="center">_integer</td>
<td align="center">int</td>
</tr>
<tr>
<td align="center">_double</td>
<td align="center">double</td>
</tr>
<tr>
<td align="center">_float</td>
<td align="center">float</td>
</tr>
<tr>
<td align="center">_boolean</td>
<td align="center">boolean</td>
</tr>
<tr>
<td align="center">string</td>
<td align="center">String</td>
</tr>
<tr>
<td align="center">byte</td>
<td align="center">Byte</td>
</tr>
<tr>
<td align="center">long</td>
<td align="center">Long</td>
</tr>
<tr>
<td align="center">short</td>
<td align="center">Short</td>
</tr>
<tr>
<td align="center">int</td>
<td align="center">Integer</td>
</tr>
<tr>
<td align="center">integer</td>
<td align="center">Integer</td>
</tr>
<tr>
<td align="center">double</td>
<td align="center">Double</td>
</tr>
<tr>
<td align="center">float</td>
<td align="center">Float</td>
</tr>
<tr>
<td align="center">boolean</td>
<td align="center">Boolean</td>
</tr>
<tr>
<td align="center">date</td>
<td align="center">Date</td>
</tr>
<tr>
<td align="center">decimal</td>
<td align="center">BigDecimal</td>
</tr>
<tr>
<td align="center">bigdecimal</td>
<td align="center">BigDecimal</td>
</tr>
<tr>
<td align="center">object</td>
<td align="center">Object</td>
</tr>
<tr>
<td align="center">map</td>
<td align="center">Map</td>
</tr>
<tr>
<td align="center">hashmap</td>
<td align="center">HashMap</td>
</tr>
<tr>
<td align="center">list</td>
<td align="center">List</td>
</tr>
<tr>
<td align="center">arraylist</td>
<td align="center">ArrayList</td>
</tr>
<tr>
<td align="center">collection</td>
<td align="center">Collection</td>
</tr>
<tr>
<td align="center">iterator</td>
<td align="center">Iterator</td>
</tr>
</tbody></table>
<h3 id="4-typeHandlers（类处理器）"><a href="#4-typeHandlers（类处理器）" class="headerlink" title="4. typeHandlers（类处理器）"></a>4. typeHandlers（类处理器）</h3><p>之后再说</p>
<h3 id="5-plugins（插件）"><a href="#5-plugins（插件）" class="headerlink" title="5. plugins（插件）"></a>5. plugins（插件）</h3><p>之后再说</p>
<h3 id="6-environments（环境配置）"><a href="#6-environments（环境配置）" class="headerlink" title="6. environments（环境配置）"></a>6. environments（环境配置）</h3><p>MyBatis 可以配置成适应多种环境，可以达到快速切换环境的目的，例如开发、测试、生产环境的切换，不同数据库之间的切换</p>
<p><strong>environments 元素定义了如何配置环境</strong></p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">environments</span> <span class="hljs-attr">default</span>=<span class="hljs-string">&quot;development&quot;</span>&gt;</span><br>    <br>    <span class="hljs-tag">&lt;<span class="hljs-name">environment</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;development&quot;</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">transactionManager</span> <span class="hljs-attr">type</span>=<span class="hljs-string">&quot;JDBC&quot;</span>/&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">dataSource</span> <span class="hljs-attr">type</span>=<span class="hljs-string">&quot;POOLED&quot;</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;driver&quot;</span> <span class="hljs-attr">value</span>=<span class="hljs-string">&quot;$&#123;jdbc.driver&#125;&quot;</span>/&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;url&quot;</span> <span class="hljs-attr">value</span>=<span class="hljs-string">&quot;$&#123;jdbc.url&#125;&quot;</span>/&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;username&quot;</span> <span class="hljs-attr">value</span>=<span class="hljs-string">&quot;$&#123;jdbc.username&#125;&quot;</span>/&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;password&quot;</span> <span class="hljs-attr">value</span>=<span class="hljs-string">&quot;$&#123;jdbc.password&#125;&quot;</span>/&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">dataSource</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">environment</span>&gt;</span><br>    <br><span class="hljs-tag">&lt;/<span class="hljs-name">environments</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p><code>&lt;environments&gt;</code> 标签中的 <code>default</code> 属性是用来指定默认的环境，填的是各个 <code>&lt;environment&gt;</code> 标签的 <code>id</code> 属性是值</p>
<p>因为一个 SqlSessionFactory 实例对应一个环境，在对象创建的时候，是要可以指定要使用那个环境的，当在 build 方法中没有传入环境信息时，使用的就是默认环境，即：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs java">SqlSessionFactory factory = <span class="hljs-keyword">new</span> SqlSessionFactoryBuilder().build(reader);<br>或<br>SqlSessionFactory factory = <span class="hljs-keyword">new</span> SqlSessionFactoryBuilder().build(reader, 配置信息);<br></code></pre></td></tr></table></figure>

<p>当要使用别的环境的时候，可以指定环境id：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs java">SqlSessionFactory factory = <span class="hljs-keyword">new</span> SqlSessionFactoryBuilder().build(reader, 环境id);<br>或<br>SqlSessionFactory factory = <span class="hljs-keyword">new</span> SqlSessionFactoryBuilder().build(reader, 环境id, 配置信息);<br></code></pre></td></tr></table></figure>



<p><strong>environment 元素定义了一个环境的详细信息</strong>，其中</p>
<ul>
<li><p>每个 environment 元素定义的环境 ID（比如：id=”development”）。</p>
</li>
<li><p><strong>transactionManager</strong>：事务管理器：</p>
<p>在 MyBatis 中有两种类型的事务管理器，就是 type=”[<strong>JDBC</strong> | <strong>MANAGED</strong>]”，之后在使用 Spring 整合 MyBatis 时会使用自带的管理器来覆盖前面的配置，因此这个我们可以不用配置，使用默认的就行</p>
</li>
<li><p><strong>dataSource</strong>：数据源的配置：</p>
<p>type 属性指定数据库连接池类型，内置的连接池有：UNPOOLED、POOLED、JNDI，当然还可以使用第三方的连接池，如：C3P0，<a target="_blank" rel="noopener" href="https://blog.csdn.net/gybshen/article/details/85997396">Druid</a></p>
<p>property 元素就是指定数据库的配置信息了，可以直接指定或者从配置文件中动态获取</p>
</li>
</ul>
<h3 id="7-databaseIdProvider（数据库厂商标识）"><a href="#7-databaseIdProvider（数据库厂商标识）" class="headerlink" title="7. databaseIdProvider（数据库厂商标识）"></a>7. databaseIdProvider（数据库厂商标识）</h3><p>MyBatis 可以<strong>根据不同的数据库厂商执行不同的语句</strong>，这种多厂商的支持是基于<strong>映射文件中的映射语句中</strong>的 <code>databaseId</code> 属性。</p>
<p>在加载映射语句的时候，如果两个映射语句形同，但是一个有 databaseI 属性，一个不带，则只会加载带 databaseId 属性的语句。</p>
<p>为开启对多数据库的支持，只要在核心配置文件中加入</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">databaseIdProvider</span> <span class="hljs-attr">type</span>=<span class="hljs-string">&quot;DB_VENDOR&quot;</span> /&gt;</span><br></code></pre></td></tr></table></figure>

<p><code>DB_VENDOR</code> 是 mybatis 中的类 <code>VendorDatabaseIdProvider</code> 的缩写，作用是通过 <code>getDatabaseProductName()</code> 方法获取数据库驱动中的<strong>数据库标识</strong>，然后为映射语句的 <code>databaseId</code> 赋值。</p>
<p>常见的数据库的默认数据库标识有：MYSQL、Oracle、SQL Server、DB2，我们还可以为其起好记的别名，这个别名之后就可以在为 <code>databaseId</code> 赋值时使用</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-comment">&lt;!-- 多数据库环境支持 --&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">databaseIdProvider</span> <span class="hljs-attr">type</span>=<span class="hljs-string">&quot;DB_VENDOR&quot;</span>&gt;</span><br>    <span class="hljs-comment">&lt;!-- 为不同的数据库厂商起别名 --&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;MYSQL&quot;</span> <span class="hljs-attr">value</span>=<span class="hljs-string">&quot;mysql&quot;</span>/&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;SQL Server&quot;</span> <span class="hljs-attr">value</span>=<span class="hljs-string">&quot;sqlserver&quot;</span>/&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;DB2&quot;</span> <span class="hljs-attr">value</span>=<span class="hljs-string">&quot;db2&quot;</span>/&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;Oracle&quot;</span> <span class="hljs-attr">value</span>=<span class="hljs-string">&quot;oracle&quot;</span> /&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">databaseIdProvider</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p>例如，我现在既想使用 mysql 还想使用 oracle 数据库，我就可以再引入 oracle  的驱动，配置 oracle 的环境</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">environments</span> <span class="hljs-attr">default</span>=<span class="hljs-string">&quot;dev_oracle&quot;</span>&gt;</span><br>    <span class="hljs-comment">&lt;!-- mysql 数据库环境 --&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">environment</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;dev_mysql&quot;</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">transactionManager</span> <span class="hljs-attr">type</span>=<span class="hljs-string">&quot;JDBC&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">transactionManager</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">dataSource</span> <span class="hljs-attr">type</span>=<span class="hljs-string">&quot;POOLED&quot;</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;driver&quot;</span> <span class="hljs-attr">value</span>=<span class="hljs-string">&quot;$&#123;jdbc.driver&#125;&quot;</span> /&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;url&quot;</span> <span class="hljs-attr">value</span>=<span class="hljs-string">&quot;$&#123;jdbc.url&#125;&quot;</span> /&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;username&quot;</span> <span class="hljs-attr">value</span>=<span class="hljs-string">&quot;$&#123;jdbc.username&#125;&quot;</span> /&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;password&quot;</span> <span class="hljs-attr">value</span>=<span class="hljs-string">&quot;$&#123;jdbc.password&#125;&quot;</span> /&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">dataSource</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">environment</span>&gt;</span><br>    <br>	 <span class="hljs-comment">&lt;!-- oracle 数据库环境 --&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">environment</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;dev_oracle&quot;</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">transactionManager</span> <span class="hljs-attr">type</span>=<span class="hljs-string">&quot;JDBC&quot;</span> /&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">dataSource</span> <span class="hljs-attr">type</span>=<span class="hljs-string">&quot;POOLED&quot;</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;driver&quot;</span> <span class="hljs-attr">value</span>=<span class="hljs-string">&quot;$&#123;oracle.driver&#125;&quot;</span> /&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;url&quot;</span> <span class="hljs-attr">value</span>=<span class="hljs-string">&quot;$&#123;oracle.url&#125;&quot;</span> /&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;username&quot;</span> <span class="hljs-attr">value</span>=<span class="hljs-string">&quot;$&#123;oracle.username&#125;&quot;</span> /&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;password&quot;</span> <span class="hljs-attr">value</span>=<span class="hljs-string">&quot;$&#123;oracle.password&#125;&quot;</span> /&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">dataSource</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">environment</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">environments</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p> 现在，我们在映射语句中写上两个数据的库的查询语句</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">mapper</span> <span class="hljs-attr">namespace</span>=<span class="hljs-string">&quot;cn.yechen.mapper.StudentMapper&quot;</span>&gt;</span><br>    <span class="hljs-comment">&lt;!-- mysql 的查询语句 --&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">select</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;selectOne&quot;</span> <span class="hljs-attr">resultType</span>=<span class="hljs-string">&quot;student&quot;</span> <span class="hljs-attr">databaseId</span>=<span class="hljs-string">&quot;mysql&quot;</span>&gt;</span><br>        select * from student where id=#&#123;id&#125;<br>    <span class="hljs-tag">&lt;/<span class="hljs-name">select</span>&gt;</span><br><br>    <span class="hljs-comment">&lt;!-- oracle 的查询语句 --&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">select</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;selectOne&quot;</span> <span class="hljs-attr">resultType</span>=<span class="hljs-string">&quot;student&quot;</span> <span class="hljs-attr">databaseId</span>=<span class="hljs-string">&quot;oracle&quot;</span>&gt;</span><br>        select * from student where id=#&#123;id&#125;<br>    <span class="hljs-tag">&lt;/<span class="hljs-name">select</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">mapper</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p>这样配置之后，想要使用不同的数据库，只要<strong>更改 environments 标签中的 default 属性</strong>，就可指定不同是数据库，执行当前数据库对应的 sql 语句</p>
<h3 id="8-mappers（映射器）"><a href="#8-mappers（映射器）" class="headerlink" title="8. mappers（映射器）"></a>8. mappers（映射器）</h3><p>用于指定 sql 映射文件，将 sql 映射文件注册到全局配置文件中。</p>
<p>有四种配置方式：</p>
<ul>
<li><p>方式一：类路径的资源引用     </p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">mappers</span>&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">mapper</span> <span class="hljs-attr">resource</span>=<span class="hljs-string">&quot;mybatis/mapper/StudentMapper.xml&quot;</span>/&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">mappers</span>&gt;</span><br></code></pre></td></tr></table></figure></li>
<li><p>方式二：完全限定资源定位符应用</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">mappers</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">mapper</span> <span class="hljs-attr">url</span>=<span class="hljs-string">&quot;file:///D:/Desktop/mybatis/code/mybatis-hello/src/main/resources/StudentMapper.xml&quot;</span>/&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">mappers</span>&gt;</span><br></code></pre></td></tr></table></figure></li>
<li><p>方式三：指定 mapper 映射接口的权限定类名（但这样指定有一个限制，sql 映射文件一定要接口同名，并且两个文件在一个目录下）</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">mappers</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">mapper</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;cn.yechen.mapper.StudentMapper&quot;</span>/&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">mappers</span>&gt;</span><br></code></pre></td></tr></table></figure></li>
<li><p>方式四：指定 mapper 映射接口的包名，批量注册</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">mappers</span>&gt;</span><br>    <span class="hljs-comment">&lt;!-- mapper 文件所在的包名 --&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">package</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;cn.yechen.mapper&quot;</span>/&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">mappers</span>&gt;</span><br></code></pre></td></tr></table></figure></li>
</ul>
<h3 id="9-配置顺序"><a href="#9-配置顺序" class="headerlink" title="9.配置顺序"></a>9.配置顺序</h3><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-comment">&lt;!-- 配置顺序如下</span><br><span class="hljs-comment">     properties  </span><br><span class="hljs-comment"></span><br><span class="hljs-comment">     settings</span><br><span class="hljs-comment"></span><br><span class="hljs-comment">     typeAliases</span><br><span class="hljs-comment"></span><br><span class="hljs-comment">     typeHandlers</span><br><span class="hljs-comment"></span><br><span class="hljs-comment">     objectFactory</span><br><span class="hljs-comment"></span><br><span class="hljs-comment">     plugins</span><br><span class="hljs-comment"></span><br><span class="hljs-comment">     environments</span><br><span class="hljs-comment">        environment</span><br><span class="hljs-comment">            transactionManager</span><br><span class="hljs-comment">            dataSource</span><br><span class="hljs-comment"></span><br><span class="hljs-comment">     mappers</span><br><span class="hljs-comment"> --&gt;</span><br></code></pre></td></tr></table></figure>



<h2 id="四、MyBatis-映射文件"><a href="#四、MyBatis-映射文件" class="headerlink" title="四、MyBatis 映射文件"></a>四、MyBatis 映射文件</h2><p>MyBatis 的真正强大在于它的语句映射，这是它的魔力所在。由于它的异常强大，映射器的 XML 文件就显得相对简单。如果拿它跟具有相同功能的 JDBC 代码进行对比，你会立即发现省掉了将近 95% 的代码。MyBatis 致力于减少使用成本，让用户能更专注于 SQL 代码。</p>
<p>SQL 映射文件只有很少的几个顶级元素：</p>
<ul>
<li><code>cache</code>：该命名空间的缓存配置</li>
<li><code>cache-ref</code>：引用其他命名空间的缓存配置</li>
<li><code>resultMap</code>：描述从数据中获取数据后对数据的封装对象</li>
<li><code>sql</code>：可以被重复引用的 sql 语句块</li>
<li><code>insert</code>：映射插入语句</li>
<li><code>update</code>：映射更新语句</li>
<li><code>delete</code>：映射删除语句</li>
<li><code>select</code>：映射查询语句</li>
</ul>
<h3 id="1-insert、update、delete"><a href="#1-insert、update、delete" class="headerlink" title="1. insert、update、delete"></a>1. insert、update、delete</h3><p>以下是一些属性解释，详细见<a target="_blank" rel="noopener" href="https://mybatis.org/mybatis-3/zh/sqlmap-xml.html#insert_update_and_delete">官方文档</a></p>
<p><img src="https://yechen-blog-image.oss-cn-hangzhou.aliyuncs.com/images/image-20211019163340708.png" srcset="/img/loading.gif" lazyload alt="属性列表"></p>
<h3 id="2-参数传递"><a href="#2-参数传递" class="headerlink" title="2. 参数传递"></a>2. 参数传递</h3><h4 id="一个参数时"><a href="#一个参数时" class="headerlink" title="一个参数时"></a>一个参数时</h4><p>在 sql 语句中使用 <code>#&#123;任意字符&#125;</code> 来传值。</p>
<p>例如：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">select</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;selectOne&quot;</span> <span class="hljs-attr">resultType</span>=<span class="hljs-string">&quot;student&quot;</span> <span class="hljs-attr">parameterType</span>=<span class="hljs-string">&quot;java.lang.Integer&quot;</span>&gt;</span><br>    select * from student where id=#&#123;id&#125;<br><span class="hljs-tag">&lt;/<span class="hljs-name">select</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p>其中：</p>
<p><code>&lt;paramterType&gt;</code>：表示 dao 接口中方法参数的数据类型，值是 java 类型的全限定名称，或者是 MyBatis 中已经设置好的别名。<strong>这个属性是可选的</strong>，因为 MyBatis 可以通过<strong>类型处理器（TypeHandler）推断出具体传入语句的参数</strong>，默认值为未设置（unset）。</p>
<p><strong>MyBatis  如何执行对数据库的操作：</strong></p>
<ol>
<li><p>mybatis 会创建 Connection、PreparedStatement 对象。</p>
</li>
<li><p>获取 sql 语句，将 #{} 使用占位符 ? 代替。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs java">String sql = <span class="hljs-string">&quot; select * from student where id=?&quot;</span>;<br></code></pre></td></tr></table></figure></li>
<li><p>对 PreparedStatement 对象赋值，预编译 sql。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs java">preparedStatement = connection.prepareStatement(sql);<br></code></pre></td></tr></table></figure></li>
<li><p>向 sql 语句中赋值。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs java">preparedStatement.setInt(<span class="hljs-number">1</span>, id);<br></code></pre></td></tr></table></figure></li>
<li><p>执行 sql，获取结果集。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs java">ResultSet resultSet = preparedStatement.executeQuery();<br></code></pre></td></tr></table></figure></li>
<li><p>将查询结果封住为 resultType 属性的执行的类型，返回给对象。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs java">Student student = <span class="hljs-keyword">null</span>;<br><span class="hljs-keyword">while</span>(resultSet.next()) &#123;<br>    student = <span class="hljs-keyword">new</span> Student();<br>    student.setInt(resultSet.getInt(<span class="hljs-string">&quot;id&quot;</span>));<br>    student.setName(resultSet.getString(<span class="hljs-string">&quot;name&quot;</span>));<br>    student.setEmail(resultSet.getString(<span class="hljs-string">&quot;email&quot;</span>));<br>    student.setAge(resultSet.getInt(<span class="hljs-string">&quot;age&quot;</span>));<br>&#125;<br><span class="hljs-keyword">return</span> student;<br></code></pre></td></tr></table></figure></li>
</ol>
<h4 id="多个参数时"><a href="#多个参数时" class="headerlink" title="多个参数时"></a>多个参数时</h4><p>当方法中存在多个参数的时候，如果还是使用 <code>#&#123;参数名&#125;</code> ,会出现什么情况呢</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">select</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;selectByNameAndAge&quot;</span> <span class="hljs-attr">resultType</span>=<span class="hljs-string">&quot;student&quot;</span>&gt;</span><br>    select * from student where stu_name=#&#123;name&#125; and age=#&#123;age&#125;<br><span class="hljs-tag">&lt;/<span class="hljs-name">select</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p>出现错误：</p>
<figure class="highlight clean"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs clean">org.apache.ibatis.exceptions.PersistenceException: <br>### Error querying database.  Cause: org.apache.ibatis.binding.BindingException: Parameter <span class="hljs-string">&#x27;name&#x27;</span> not found. Available parameters are [arg1, arg0, param1, param2]<br>### Cause: org.apache.ibatis.binding.BindingException: Parameter <span class="hljs-string">&#x27;name&#x27;</span> not found. Available parameters are [arg1, arg0, param1, param2]<br></code></pre></td></tr></table></figure>

<p>原因是在有多个数据的时候 MyBaits 会将多个<strong>数据封装为一个 map</strong>，<code>key</code> 是 <strong>param1、param2… 或 arg0、arg1…</strong> ，<code>value</code> 是<strong>传递进来的参数</strong></p>
<p>因此想要获取到参数，需要使用对应的 key 来获取 vlaue 值，即：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">select</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;selectByNameAndAge&quot;</span> <span class="hljs-attr">resultType</span>=<span class="hljs-string">&quot;student&quot;</span>&gt;</span><br>    select * from student where stu_name=#&#123;param1&#125; and age=#&#123;param2&#125;<br><span class="hljs-tag">&lt;/<span class="hljs-name">select</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p>或</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">select</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;selectByNameAndAge&quot;</span> <span class="hljs-attr">resultType</span>=<span class="hljs-string">&quot;student&quot;</span>&gt;</span><br>    select * from student where stu_name=#&#123;arg0&#125; and age=#&#123;arg1&#125;<br><span class="hljs-tag">&lt;/<span class="hljs-name">select</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p><img src="https://yechen-blog-image.oss-cn-hangzhou.aliyuncs.com/images/image-20211019170817135.png" srcset="/img/loading.gif" lazyload alt="查询结果"></p>
<p>但是如果这样写的话，在 sql 语句中参数名称显示不直观，当参数一多，sql 都看不懂了，所以有以下的方法来解决这个问题</p>
<h5 id="方法一-：-Param注解"><a href="#方法一-：-Param注解" class="headerlink" title="方法一 ：@Param注解"></a>方法一 ：@Param注解</h5><p>在接口中的方法参数使用 <code>@Param(&quot;自定义名称&quot;)</code> 命名，mapper 中使用 <code>#&#123;自定义名称&#125;</code>。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">// dao 接口</span><br><span class="hljs-function">Student <span class="hljs-title">selectByNameAndAge</span><span class="hljs-params">(<span class="hljs-meta">@Param(&quot;name&quot;)</span>String name, <span class="hljs-meta">@Param(&quot;age&quot;)</span>Integer age)</span></span>;<br></code></pre></td></tr></table></figure>

<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-comment">&lt;!-- mapper 文件 --&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">select</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;selectByNameAndAge&quot;</span> <span class="hljs-attr">resultType</span>=<span class="hljs-string">&quot;student&quot;</span>&gt;</span><br>    select * from student where stu_name=#&#123;name&#125; and age=#&#123;age&#125;<br><span class="hljs-tag">&lt;/<span class="hljs-name">select</span>&gt;</span><br></code></pre></td></tr></table></figure>



<h5 id="方法二：Java对象"><a href="#方法二：Java对象" class="headerlink" title="方法二：Java对象"></a>方法二：Java对象</h5><p>在接口中的方法<strong>参数使用 java 对象</strong>，在 mapper 中使用 <strong>java 对象的属性值作为 sql 参数的实际值</strong>，这个 java 对象可以是使用时封装的<strong>数据传输对象</strong>（TO 类），也可以直接使用<strong>数据库实体类</strong>（POJO 类），mapper 中使用 **#{java 对象属性名}**。</p>
<ul>
<li><strong>最完整的语法格式</strong>：#{属性名，javaType=java对象中属性的类型，jdbcType=字段在数据库中的数据类型}  但这种方法很少用。</li>
<li><strong>使用简化的方式</strong>：#{属性名} 常用，javaType 和 jdbcType 的值 mybatis 可以通过反射获取</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">// dao 接口</span><br><span class="hljs-function">Student <span class="hljs-title">selectByQueryArg</span><span class="hljs-params">(StudentQueryArg studentQueryArg)</span></span>;<br><br><span class="hljs-comment">// 自定义查询参数类</span><br><span class="hljs-meta">@Data</span><br><span class="hljs-meta">@NoArgsConstructor</span><br><span class="hljs-meta">@AllArgsConstructor</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">StudentQueryArg</span> </span>&#123;<br>    <span class="hljs-keyword">private</span> String stuName;<br>    <span class="hljs-keyword">private</span> Integer age;<br>&#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-comment">&lt;!-- mapper 文件 --&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">select</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;selectByQueryArgs&quot;</span> <span class="hljs-attr">resultType</span>=<span class="hljs-string">&quot;student&quot;</span>&gt;</span><br>    select * from student where stu_name=#&#123;stuName&#125; and age=#&#123;age&#125;<br><span class="hljs-tag">&lt;/<span class="hljs-name">select</span>&gt;</span><br></code></pre></td></tr></table></figure>



<h5 id="方法三：Map对象"><a href="#方法三：Map对象" class="headerlink" title="方法三：Map对象"></a>方法三：Map对象</h5><p>在接口中的方法<strong>参数使用 Map 类型对象</strong>，mapper 中使用 <strong>#{map对象的 key}</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">// dao 接口</span><br><span class="hljs-function">List&lt;Student&gt; <span class="hljs-title">selectMultiMap</span><span class="hljs-params">(Map&lt;String, Object&gt; map)</span></span>;<br><br><span class="hljs-comment">// 测试方法</span><br><span class="hljs-meta">@Test</span><br><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">testMap</span><span class="hljs-params">()</span> </span>&#123;<br>    SqlSession sqlSession = MyBatisUtils.getSqlSession();<br>    StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);<br>    Map&lt;String, Object&gt; map = <span class="hljs-keyword">new</span> HashMap&lt;&gt;();<br>    map.put(<span class="hljs-string">&quot;stuName&quot;</span>, <span class="hljs-string">&quot;wangwu&quot;</span>);<br>    map.put(<span class="hljs-string">&quot;age&quot;</span>, <span class="hljs-number">22</span>);<br>    Student student = mapper.selectByMap(map);<br>    System.out.println(student);<br>    sqlSession.close();<br>&#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-comment">&lt;!-- mapper 文件 --&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">select</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;selectByMap&quot;</span> <span class="hljs-attr">resultType</span>=<span class="hljs-string">&quot;student&quot;</span>&gt;</span><br>    select * from student where stu_name=#&#123;stuName&#125; and age=#&#123;age&#125;<br><span class="hljs-tag">&lt;/<span class="hljs-name">select</span>&gt;</span><br></code></pre></td></tr></table></figure>



<h4 id="参数传递时-和-的区别"><a href="#参数传递时-和-的区别" class="headerlink" title="参数传递时 # 和 $ 的区别"></a>参数传递时 # 和 $ 的区别</h4><p><code>#</code>：是 mybatis 中的占位符，告诉 mybatis 使用实际的参数值代替。并<strong>使用 PrepareStatement 对象执行 sql 语句, #{…} 代替 sql 语句的 “?”</strong>。这样做更安全(可以避免 sql 注入)，更迅速，通常也是首选做法。</p>
<p><code>$</code>：是 mybatis 中的占位符，表示字符串替换，告诉 mybatis 使用 <code>$</code> 包含的“字符串”替换所在位置。<strong>使用 Statement 把 sql 语句和 ${…} 的内容连接起来</strong>。主要用在替换表名，列名，不同列排序等操作。会有 sql 注入等安全风险。</p>
<h3 id="3-select"><a href="#3-select" class="headerlink" title="3. select"></a>3. select</h3><p>以下是一些属性解释，详细见<a target="_blank" rel="noopener" href="https://mybatis.org/mybatis-3/zh/sqlmap-xml.html#select">官方文档</a></p>
<p><img src="https://yechen-blog-image.oss-cn-hangzhou.aliyuncs.com/images/image-20211019173057204.png" srcset="/img/loading.gif" lazyload alt="select 标签属性"></p>
<p><code>resultType</code>：属性指定的是结果类型，sql 语句执行完成之后，mybatis 调用指定的 java 类的无参构造方法，创建对应的对象。使用时要保证指定 java 类中的属性和数据库字段的名称要一致（或者开启自动驼峰命名规则映射功能，mapUnderscoreToCamelCase=true），并存在属性对应的 get 和 set 方法，mybatis 会将 ResultSet 对象中的指定列值赋给同名的属性。</p>
<p><code>resultType 属性值</code>可以是：</p>
<ul>
<li>类型的全限定名称，比如类 Integer 就要写成 java.lang.Integer。</li>
<li>由 mybatis 官方文档中指定的常用类型的别名，如 java.lang.Integer 的别名就是 int。</li>
</ul>
<p>当返回值类型是一个 <code>集合</code> 的时候，<code>resultType</code> 要指定集合种保存的数据的类型，如</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">// dao 接口方法</span><br><span class="hljs-function">List&lt;Student&gt; <span class="hljs-title">selectAll</span><span class="hljs-params">()</span></span>;<br></code></pre></td></tr></table></figure>

<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-comment">&lt;!-- mapper 文件 --&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">select</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;selectAll&quot;</span> <span class="hljs-attr">resultType</span>=<span class="hljs-string">&quot;student&quot;</span>&gt;</span><br>    select * from student<br><span class="hljs-tag">&lt;/<span class="hljs-name">select</span>&gt;</span><br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">// 测试方法</span><br><span class="hljs-meta">@Test</span><br><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">testSelectAll</span><span class="hljs-params">()</span> </span>&#123;<br>    SqlSession sqlSession = MyBatisUtils.getSqlSession();<br>    StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);<br>    List&lt;Student&gt; students = mapper.selectAll();<br>    students.forEach(System.out::println);<br>&#125;<br></code></pre></td></tr></table></figure>

<p><img src="https://yechen-blog-image.oss-cn-hangzhou.aliyuncs.com/images/image-20211019200310204.png" srcset="/img/loading.gif" lazyload alt="测试结果"></p>
<p>当返回值是一个 <code>Map</code> 的时候，<code>resultType</code> 就可以指定为 map，将查询结果保存为一个 map，key 为数据库字段名，value 为查询到的值</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">// dao 接口方法</span><br><span class="hljs-function">Map&lt;String, Object&gt; <span class="hljs-title">selectMap</span><span class="hljs-params">(Integer id)</span></span>;<br></code></pre></td></tr></table></figure>

<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-comment">&lt;!-- mapper 文件 --&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">select</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;selectMap&quot;</span> <span class="hljs-attr">resultType</span>=<span class="hljs-string">&quot;map&quot;</span>&gt;</span><br>    select * from student where id=#&#123;id&#125;<br><span class="hljs-tag">&lt;/<span class="hljs-name">select</span>&gt;</span><br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">// 测试方法</span><br><span class="hljs-meta">@Test</span><br><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">testSelectMap</span><span class="hljs-params">()</span> </span>&#123;<br>    SqlSession sqlSession = MyBatisUtils.getSqlSession();<br>    StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);<br>    Map&lt;String, Object&gt; map = mapper.selectMap(<span class="hljs-number">1</span>);<br>    map.forEach((key, value) -&gt; &#123;<br>        System.out.println(<span class="hljs-string">&quot;key = &quot;</span> + key + <span class="hljs-string">&quot;，value = &quot;</span> + value);<br>    &#125;);<br>&#125;<br></code></pre></td></tr></table></figure>

<p><img src="https://yechen-blog-image.oss-cn-hangzhou.aliyuncs.com/images/image-20211019201013454.png" srcset="/img/loading.gif" lazyload alt="测试结果"></p>
<h3 id="4-resultMap"><a href="#4-resultMap" class="headerlink" title="4. resultMap"></a>4. resultMap</h3><p>当数据库列名和 JavaBean 的属性名不一致时，我们可以在查询语句中为列名起别名，如果列名和属性名符合驼峰命名法，还可以开启 mapUnderscoreToCamelCase 属性设置，这些都是解决简单问题的方法。</p>
<p>当映射关系复杂的时候，使用 <code>resultMap</code> 自定义结果集映射方法是最方便的方法。</p>
<h4 id="简单使用一下-resultMap"><a href="#简单使用一下-resultMap" class="headerlink" title="简单使用一下 resultMap"></a>简单使用一下 resultMap</h4><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">resultMap</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;studentResultMap&quot;</span> <span class="hljs-attr">type</span>=<span class="hljs-string">&quot;cn.yechen.bean.Student&quot;</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">id</span> <span class="hljs-attr">column</span>=<span class="hljs-string">&quot;id&quot;</span> <span class="hljs-attr">property</span>=<span class="hljs-string">&quot;id&quot;</span>/&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">result</span> <span class="hljs-attr">column</span>=<span class="hljs-string">&quot;stu_name&quot;</span> <span class="hljs-attr">property</span>=<span class="hljs-string">&quot;stuName&quot;</span>/&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">result</span> <span class="hljs-attr">column</span>=<span class="hljs-string">&quot;email&quot;</span> <span class="hljs-attr">property</span>=<span class="hljs-string">&quot;email&quot;</span>/&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">result</span> <span class="hljs-attr">column</span>=<span class="hljs-string">&quot;age&quot;</span> <span class="hljs-attr">property</span>=<span class="hljs-string">&quot;age&quot;</span>/&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">resultMap</span>&gt;</span><br></code></pre></td></tr></table></figure>

<ul>
<li>resultMap 中的 id 是自定义的名称，之后使用到，type 是结果映射的 Java 对象，可以写简写</li>
<li>id 指定主键，result 指定普通列</li>
<li>column 属性指定数据库中的列名，property 指定 JavaBean 中的属性名，这样就可以一一对应了</li>
</ul>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">select</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;selectOne&quot;</span> <span class="hljs-attr">resultMap</span>=<span class="hljs-string">&quot;studentResultMap&quot;</span>&gt;</span><br>    select * from student where id=#&#123;id&#125;<br><span class="hljs-tag">&lt;/<span class="hljs-name">select</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p><img src="https://yechen-blog-image.oss-cn-hangzhou.aliyuncs.com/images/image-20211019204807027.png" srcset="/img/loading.gif" lazyload alt="测试结果"></p>
<h4 id="association-标签"><a href="#association-标签" class="headerlink" title="association 标签"></a>association 标签</h4><blockquote>
<p>一个复杂类型的关联，许多结果将包装成这种类型</p>
<p>嵌套结果映射 – 关联可以是 <code>resultMap</code> 元素，或是对其它结果映射的引用</p>
</blockquote>
<h5 id="复杂一下我们的业务"><a href="#复杂一下我们的业务" class="headerlink" title="复杂一下我们的业务"></a>复杂一下我们的业务</h5><ol>
<li><p>新建一张班级表</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-keyword">DROP</span> <span class="hljs-keyword">TABLE</span> IF <span class="hljs-keyword">EXISTS</span> `class`;<br><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> `class`  (<br>  `id` <span class="hljs-type">int</span>(<span class="hljs-number">0</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> AUTO_INCREMENT,<br>  `class_name` <span class="hljs-type">varchar</span>(<span class="hljs-number">255</span>) <span class="hljs-type">CHARACTER</span> <span class="hljs-keyword">SET</span> utf8 <span class="hljs-keyword">COLLATE</span> utf8_croatian_ci <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-keyword">NULL</span>,<br>  `teacher_name` <span class="hljs-type">varchar</span>(<span class="hljs-number">255</span>) <span class="hljs-type">CHARACTER</span> <span class="hljs-keyword">SET</span> utf8 <span class="hljs-keyword">COLLATE</span> utf8_croatian_ci <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-keyword">NULL</span>,<br>  <span class="hljs-keyword">PRIMARY</span> KEY (`id`) <span class="hljs-keyword">USING</span> BTREE<br>) ENGINE <span class="hljs-operator">=</span> InnoDB <span class="hljs-type">CHARACTER</span> <span class="hljs-keyword">SET</span> <span class="hljs-operator">=</span> utf8 <span class="hljs-keyword">COLLATE</span> <span class="hljs-operator">=</span> utf8_croatian_ci ROW_FORMAT <span class="hljs-operator">=</span> <span class="hljs-keyword">Dynamic</span>;<br><br><span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> `class` <span class="hljs-keyword">VALUES</span> (<span class="hljs-number">1</span>, <span class="hljs-string">&#x27;高三一班&#x27;</span>, <span class="hljs-string">&#x27;tom&#x27;</span>);<br><span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> `class` <span class="hljs-keyword">VALUES</span> (<span class="hljs-number">2</span>, <span class="hljs-string">&#x27;高三二班&#x27;</span>, <span class="hljs-string">&#x27;jack&#x27;</span>);<br></code></pre></td></tr></table></figure></li>
<li><p>为学生表添加一个字段保存班级 id，将两张表联系起来</p>
<p><img src="https://yechen-blog-image.oss-cn-hangzhou.aliyuncs.com/images/image-20211019223947470.png" srcset="/img/loading.gif" lazyload alt="学生表数据"></p>
</li>
<li><p>创建班级实体列，修改学生实体类</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Data</span><br><span class="hljs-meta">@NoArgsConstructor</span><br><span class="hljs-meta">@AllArgsConstructor</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TheClass</span> </span>&#123;<br>    <span class="hljs-keyword">private</span> Integer id;<br>    <span class="hljs-keyword">private</span> String className;<br>    <span class="hljs-keyword">private</span> String teacherName;<br>&#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Data</span><br><span class="hljs-meta">@NoArgsConstructor</span><br><span class="hljs-meta">@AllArgsConstructor</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Student</span> </span>&#123;<br>    <span class="hljs-keyword">private</span> Integer id;<br>    <span class="hljs-keyword">private</span> String stuName;<br>    <span class="hljs-keyword">private</span> String email;<br>    <span class="hljs-keyword">private</span> Integer age;<br>    <span class="hljs-keyword">private</span> TheClass theClass;<br>&#125;<br></code></pre></td></tr></table></figure></li>
<li><p>dao 接口方法，sql 映射，测试方法</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-function">Student <span class="hljs-title">getStudentAndClass</span><span class="hljs-params">(Integer id)</span></span>;<br></code></pre></td></tr></table></figure>

<p>resultMap 标签中的 <code>association</code> 标签，可以嵌套结果映射，在 Student 类中 theClass 是一个对象，就可以使用 association 标签为对象中的属性一一赋值</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">resultMap</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;studentResultMapPlus&quot;</span> <span class="hljs-attr">type</span>=<span class="hljs-string">&quot;cn.yechen.bean.Student&quot;</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">id</span> <span class="hljs-attr">column</span>=<span class="hljs-string">&quot;id&quot;</span> <span class="hljs-attr">property</span>=<span class="hljs-string">&quot;id&quot;</span>/&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">result</span> <span class="hljs-attr">column</span>=<span class="hljs-string">&quot;stu_name&quot;</span> <span class="hljs-attr">property</span>=<span class="hljs-string">&quot;stuName&quot;</span>/&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">result</span> <span class="hljs-attr">column</span>=<span class="hljs-string">&quot;email&quot;</span> <span class="hljs-attr">property</span>=<span class="hljs-string">&quot;email&quot;</span>/&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">result</span> <span class="hljs-attr">column</span>=<span class="hljs-string">&quot;age&quot;</span> <span class="hljs-attr">property</span>=<span class="hljs-string">&quot;age&quot;</span>/&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">association</span> <span class="hljs-attr">property</span>=<span class="hljs-string">&quot;theClass&quot;</span> <span class="hljs-attr">javaType</span>=<span class="hljs-string">&quot;cn.yechen.bean.TheClass&quot;</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">id</span> <span class="hljs-attr">column</span>=<span class="hljs-string">&quot;cid&quot;</span> <span class="hljs-attr">property</span>=<span class="hljs-string">&quot;id&quot;</span>/&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">result</span> <span class="hljs-attr">column</span>=<span class="hljs-string">&quot;class_name&quot;</span> <span class="hljs-attr">property</span>=<span class="hljs-string">&quot;className&quot;</span>/&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">result</span> <span class="hljs-attr">column</span>=<span class="hljs-string">&quot;teacher_name&quot;</span> <span class="hljs-attr">property</span>=<span class="hljs-string">&quot;teacherName&quot;</span>/&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">association</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">resultMap</span>&gt;</span><br><br><span class="hljs-tag">&lt;<span class="hljs-name">select</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;getStudentAndClass&quot;</span> <span class="hljs-attr">resultMap</span>=<span class="hljs-string">&quot;studentResultMapPlus&quot;</span>&gt;</span><br>    select s.id as id, s.stu_name, s.email, s.age, s.class_id,c.id as cid, c.class_name, c.teacher_name<br>    from student as s<br>    join class as c<br>    on s.class_id=c.id<br>    where s.id=#&#123;id&#125;<br><span class="hljs-tag">&lt;/<span class="hljs-name">select</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p>测试方法</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Test</span><br><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">testResultMap</span><span class="hljs-params">()</span> </span>&#123;<br>    SqlSession sqlSession = MyBatisUtils.getSqlSession();<br>    StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);<br>    Student student = mapper.getStudentAndClass(<span class="hljs-number">1</span>);<br>    System.out.println(student);<br>&#125;<br></code></pre></td></tr></table></figure>

<p><img src="https://yechen-blog-image.oss-cn-hangzhou.aliyuncs.com/images/image-20211019224653057.png" srcset="/img/loading.gif" lazyload alt="测试结果"></p>
</li>
</ol>
<h5 id="分步查询"><a href="#分步查询" class="headerlink" title="分步查询"></a>分步查询</h5><p>在 resultMap 中可以将 sql 分开，前一个 sql 的查询结果作为后一个 sql 的查询条件，简化 sql，复用 sql</p>
<ol>
<li><p>先在 TheClassMapper 接口中定义一个方法，通过 id 查询班级，并在 mapper 文件中写上对应 sql</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">TheClassMapper</span> </span>&#123;<br>    <span class="hljs-function">TheClass <span class="hljs-title">getClassById</span><span class="hljs-params">(Integer id)</span></span>;<br>&#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">select</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;getClassById&quot;</span> <span class="hljs-attr">resultType</span>=<span class="hljs-string">&quot;cn.yechen.bean.TheClass&quot;</span>&gt;</span><br>    select * from class where id=#&#123;classId&#125;;<br><span class="hljs-tag">&lt;/<span class="hljs-name">select</span>&gt;</span><br></code></pre></td></tr></table></figure></li>
<li><p>在 StudentMapper 定义分步查询方法，使用 resultMap 指定封装结果集</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-function">Student <span class="hljs-title">getStudentByIdThroughStep</span><span class="hljs-params">(Integer id)</span></span>;<br></code></pre></td></tr></table></figure>

<p><code>association</code> 标签中有 </p>
<ul>
<li><code>select</code> 属性，其中就是指定要使用的 sql 的 <code>namespace+id</code></li>
<li><code>column</code> 属性中指定查询条件，数据是从之前查询出来<ul>
<li>如果只有一个参数，可以直接写列名，即 <code>column=&quot;id&quot;</code></li>
<li>如果有多个参数，可以以 key=value 的形式，key 是指定 sql 查询中的 key，value 就是从查询出来的数据列名，即 <code>column=&quot;&#123;classId=id&#125;&quot;</code></li>
</ul>
</li>
</ul>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">resultMap</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;getStudentByIdThroughStep&quot;</span> <span class="hljs-attr">type</span>=<span class="hljs-string">&quot;cn.yechen.bean.Student&quot;</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">id</span> <span class="hljs-attr">column</span>=<span class="hljs-string">&quot;id&quot;</span> <span class="hljs-attr">property</span>=<span class="hljs-string">&quot;id&quot;</span>/&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">result</span> <span class="hljs-attr">column</span>=<span class="hljs-string">&quot;stu_name&quot;</span> <span class="hljs-attr">property</span>=<span class="hljs-string">&quot;stuName&quot;</span>/&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">result</span> <span class="hljs-attr">column</span>=<span class="hljs-string">&quot;email&quot;</span> <span class="hljs-attr">property</span>=<span class="hljs-string">&quot;email&quot;</span>/&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">result</span> <span class="hljs-attr">column</span>=<span class="hljs-string">&quot;age&quot;</span> <span class="hljs-attr">property</span>=<span class="hljs-string">&quot;age&quot;</span>/&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">association</span> <span class="hljs-attr">property</span>=<span class="hljs-string">&quot;theClass&quot;</span> </span><br><span class="hljs-tag">             <span class="hljs-attr">select</span>=<span class="hljs-string">&quot;cn.yechen.mapper.TheClassMapper.getClassById&quot;</span> </span><br><span class="hljs-tag">             <span class="hljs-attr">column</span>=<span class="hljs-string">&quot;&#123;classId=id&#125;&quot;</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">association</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">resultMap</span>&gt;</span><br><br><span class="hljs-tag">&lt;<span class="hljs-name">select</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;getStudentByIdThroughStep&quot;</span> <span class="hljs-attr">resultMap</span>=<span class="hljs-string">&quot;getStudentByIdThroughStep&quot;</span>&gt;</span><br>    select * from student where id=#&#123;id&#125;;<br><span class="hljs-tag">&lt;/<span class="hljs-name">select</span>&gt;</span><br></code></pre></td></tr></table></figure></li>
<li><p>测试方法</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Test</span><br><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">testResultMapThroughStep</span><span class="hljs-params">()</span> </span>&#123;<br>    SqlSession sqlSession = MyBatisUtils.getSqlSession();<br>    StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);<br>    Student student = mapper.getStudentByIdThroughStep(<span class="hljs-number">2</span>);<br>    System.out.println(student);<br>    System.out.println(student.getTheClass());<br>&#125;<br></code></pre></td></tr></table></figure></li>
</ol>
<p><img src="https://yechen-blog-image.oss-cn-hangzhou.aliyuncs.com/images/image-20211020174433044.png" srcset="/img/loading.gif" lazyload alt="测试结果"></p>
<h5 id="延迟加载（按需加载）"><a href="#延迟加载（按需加载）" class="headerlink" title="延迟加载（按需加载）"></a>延迟加载（按需加载）</h5><p>在<strong>分步查询</strong>的时候可以 只在<strong>需要的时候开启 sql 查询</strong>（关联对象延迟加载），这样就可以节省资源，例如我只在方法中要获取班级信息的时候，才去查询班级信息，别的时候就都不查询</p>
<ol>
<li><p>在全局配置文件中设置属性</p>
<table>
<thead>
<tr>
<th align="left">设置名</th>
<th align="left">描述</th>
<th align="center">有效值</th>
<th align="left">默认值</th>
</tr>
</thead>
<tbody><tr>
<td align="left">lazyLoadingEnabled</td>
<td align="left"><strong>延迟加载的全局开关</strong>。当开启时，所有关联对象都会延迟加载。 特定关联关系中可通过设置 <code>fetchType</code> 属性来覆盖该项的开关状态。</td>
<td align="center">true | false</td>
<td align="left">false</td>
</tr>
<tr>
<td align="left">aggressiveLazyLoading</td>
<td align="left">开启时，任一方法的调用都会加载该对象的所有延迟加载属性。 否则，每个延迟加载属性会按需加载（参考 <code>lazyLoadTriggerMethods</code>)。</td>
<td align="center">true | false</td>
<td align="left">false</td>
</tr>
</tbody></table>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-comment">&lt;!-- 全局设置 --&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">settings</span>&gt;</span><br>    <span class="hljs-comment">&lt;!-- 延迟加载 --&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">setting</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;lazyLoadingEnabled&quot;</span> <span class="hljs-attr">value</span>=<span class="hljs-string">&quot;true&quot;</span>/&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">setting</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;aggressiveLazyLoading&quot;</span> <span class="hljs-attr">value</span>=<span class="hljs-string">&quot;false&quot;</span>/&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">settings</span>&gt;</span><br></code></pre></td></tr></table></figure></li>
<li><p>这个时候再运行测试方法，不获取班级信息</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Test</span><br><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">testResultMapThroughStep</span><span class="hljs-params">()</span> </span>&#123;<br>    SqlSession sqlSession = MyBatisUtils.getSqlSession();<br>    StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);<br>    Student student = mapper.getStudentByIdThroughStep(<span class="hljs-number">2</span>);<br>    System.out.println(student.getStuName());<br>    <span class="hljs-comment">// System.out.println(student.getTheClass());</span><br>&#125;<br></code></pre></td></tr></table></figure>

<p><img src="https://yechen-blog-image.oss-cn-hangzhou.aliyuncs.com/images/image-20211020194335623.png" srcset="/img/loading.gif" lazyload alt="不查询关联对象"></p>
</li>
<li><p>获取班级信息</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Test</span><br><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">testResultMapThroughStep</span><span class="hljs-params">()</span> </span>&#123;<br>    SqlSession sqlSession = MyBatisUtils.getSqlSession();<br>    StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);<br>    Student student = mapper.getStudentByIdThroughStep(<span class="hljs-number">2</span>);<br>    System.out.println(student.getStuName());<br>    <span class="hljs-comment">// 获取班级信息</span><br>    System.out.println(student.getTheClass());<br>&#125;<br></code></pre></td></tr></table></figure>

<p><img src="https://yechen-blog-image.oss-cn-hangzhou.aliyuncs.com/images/image-20211020194508103.png" srcset="/img/loading.gif" lazyload alt="获取了关联对象"></p>
</li>
</ol>
<h4 id="collection-标签"><a href="#collection-标签" class="headerlink" title="collection 标签"></a>collection 标签</h4><blockquote>
<p>一个复杂类型的集合</p>
<p>嵌套结果映射 – 集合可以是 <code>resultMap</code> 元素，或是对其它结果映射的引用</p>
</blockquote>
<p>现在有个需求，查询出一个班级中的所有学生。</p>
<ol>
<li><p>在 TheClass 实体类中添加一个属性，表示学生列表</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Data</span><br><span class="hljs-meta">@NoArgsConstructor</span><br><span class="hljs-meta">@AllArgsConstructor</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TheClass</span> </span>&#123;<br>    <span class="hljs-keyword">private</span> Integer id;<br>    <span class="hljs-keyword">private</span> String className;<br>    <span class="hljs-keyword">private</span> String teacherName;<br>    <span class="hljs-comment">// 学生列表</span><br>    <span class="hljs-keyword">private</span> List&lt;Student&gt; studentList;<br>&#125;<br></code></pre></td></tr></table></figure></li>
<li><p>学生表中的查询方法</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-function">List&lt;Student&gt; <span class="hljs-title">getStudentListByClassId</span><span class="hljs-params">(Integer classId)</span></span>;<br></code></pre></td></tr></table></figure>

<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">select</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;getStudentListByClassId&quot;</span> <span class="hljs-attr">resultType</span>=<span class="hljs-string">&quot;cn.yechen.bean.Student&quot;</span>&gt;</span><br>    select * from student where class_id=#&#123;classId&#125;<br><span class="hljs-tag">&lt;/<span class="hljs-name">select</span>&gt;</span><br></code></pre></td></tr></table></figure></li>
<li><p>班级表中的查询方法，使用分步查询，并且开启延迟加载</p>
<p> <code>collection</code> 的使用基本和 <code>association</code> 一致，<code>ofType</code> 属性指定列表中存放数据的类型</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">resultMap</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;getClassAStudentList&quot;</span> <span class="hljs-attr">type</span>=<span class="hljs-string">&quot;cn.yechen.bean.TheClass&quot;</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">id</span> <span class="hljs-attr">column</span>=<span class="hljs-string">&quot;id&quot;</span> <span class="hljs-attr">property</span>=<span class="hljs-string">&quot;id&quot;</span>/&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">result</span> <span class="hljs-attr">column</span>=<span class="hljs-string">&quot;class_name&quot;</span> <span class="hljs-attr">property</span>=<span class="hljs-string">&quot;className&quot;</span>/&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">result</span> <span class="hljs-attr">column</span>=<span class="hljs-string">&quot;teacher_name&quot;</span> <span class="hljs-attr">property</span>=<span class="hljs-string">&quot;teacherName&quot;</span>/&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">collection</span> <span class="hljs-attr">property</span>=<span class="hljs-string">&quot;studentList&quot;</span> <span class="hljs-attr">ofType</span>=<span class="hljs-string">&quot;cn.yechen.bean.Student&quot;</span></span><br><span class="hljs-tag">                <span class="hljs-attr">select</span>=<span class="hljs-string">&quot;cn.yechen.mapper.StudentMapper.getStudentListByClassId&quot;</span></span><br><span class="hljs-tag">                <span class="hljs-attr">column</span>=<span class="hljs-string">&quot;&#123;classId=id&#125;&quot;</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">collection</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">resultMap</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">select</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;getClassAStudentList&quot;</span> <span class="hljs-attr">resultMap</span>=<span class="hljs-string">&quot;getClassAStudentList&quot;</span>&gt;</span><br>    select * from class where id=#&#123;id&#125;<br><span class="hljs-tag">&lt;/<span class="hljs-name">select</span>&gt;</span><br></code></pre></td></tr></table></figure></li>
<li><p>测试</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Test</span><br><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">testCollection</span><span class="hljs-params">()</span> </span>&#123;<br>    SqlSession sqlSession = MyBatisUtils.getSqlSession();<br>    TheClassMapper mapper = sqlSession.getMapper(TheClassMapper.class);<br>    TheClass theClass = mapper.getClassAStudentList(<span class="hljs-number">1</span>);<br>    System.out.println(theClass.getClassName());<br>    System.out.println(theClass.getStudentList());<br>&#125;<br></code></pre></td></tr></table></figure>

<p><img src="https://yechen-blog-image.oss-cn-hangzhou.aliyuncs.com/images/image-20211020201115138.png" srcset="/img/loading.gif" lazyload alt="测试结果"></p>
</li>
</ol>
<h2 id="五、动态-sql"><a href="#五、动态-sql" class="headerlink" title="五、动态 sql"></a>五、动态 sql</h2><p><strong>动态sql</strong>: sql 的内容是变化的，<strong>可以根据条件获取到不同的 sql 语句</strong></p>
<p>MyBatis 采用功能强大的基于 <strong>OGNL</strong> 的表达式来简化操作</p>
<p><img src="https://yechen-blog-image.oss-cn-hangzhou.aliyuncs.com/images/image-20211020212547520.png" srcset="/img/loading.gif" lazyload alt="OGNL 表达式"></p>
<h3 id="1-if"><a href="#1-if" class="headerlink" title="1. if"></a>1. if</h3><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-comment">&lt;!-- 语法 --&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">if</span> <span class="hljs-attr">test</span>=<span class="hljs-string">&quot;java 对象中的属性满足的条件&quot;</span>&gt;</span><br>    满足条件下拼接上去的 sql<br><span class="hljs-tag">&lt;/<span class="hljs-name">if</span>&gt;</span><br><span class="hljs-comment">&lt;!-- 比如：当 name 属性不为 null 且不为空时拼接 sql --&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">if</span> <span class="hljs-attr">test</span>=<span class="hljs-string">&quot;name != null and name != &#x27;&#x27;&quot;</span>&gt;</span><br>    name = #&#123;name&#125;<br><span class="hljs-tag">&lt;/<span class="hljs-name">if</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p><strong>不足</strong>：当 if 中的条件不全满足的时候，拼接后的 sql 语法可能有问题。会存在 and 或 or 的多出或者缺少，导致 sql 语法错误，如：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-function">List&lt;Student&gt; <span class="hljs-title">getStudentByConditionIf</span><span class="hljs-params">(Student student)</span></span>;<br></code></pre></td></tr></table></figure>

<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">select</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;getStudentByConditionIf&quot;</span> <span class="hljs-attr">resultType</span>=<span class="hljs-string">&quot;student&quot;</span>&gt;</span><br>    select * from student where<br>    <span class="hljs-tag">&lt;<span class="hljs-name">if</span> <span class="hljs-attr">test</span>=<span class="hljs-string">&quot;id != null&quot;</span>&gt;</span><br>        id=#&#123;id&#125;<br>    <span class="hljs-tag">&lt;/<span class="hljs-name">if</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">if</span> <span class="hljs-attr">test</span>=<span class="hljs-string">&quot;stuName != null and stuName != &#x27;&#x27;&quot;</span>&gt;</span><br>        and stu_name like #&#123;stuName&#125;<br>    <span class="hljs-tag">&lt;/<span class="hljs-name">if</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">if</span> <span class="hljs-attr">test</span>=<span class="hljs-string">&quot;email != null and email.trim() != &#x27;&#x27;&quot;</span>&gt;</span><br>        and email=#&#123;email&#125;<br>    <span class="hljs-tag">&lt;/<span class="hljs-name">if</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">if</span> <span class="hljs-attr">test</span>=<span class="hljs-string">&quot;age != null and age &gt; 0&quot;</span>&gt;</span><br>        and age=#&#123;age&#125;<br>    <span class="hljs-tag">&lt;/<span class="hljs-name">if</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">select</span>&gt;</span><br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Test</span><br><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">testIf</span><span class="hljs-params">()</span> </span>&#123;<br>    SqlSession sqlSession = MyBatisUtils.getSqlSession();<br>    StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);<br>    List&lt;Student&gt; studentList = mapper.getStudentByConditionIf(<span class="hljs-keyword">new</span> Student(<span class="hljs-keyword">null</span>, <span class="hljs-string">&quot;zhangsan&quot;</span>, <span class="hljs-keyword">null</span>, <span class="hljs-keyword">null</span>));<br>    studentList.forEach(System.out::println);<br>&#125;<br></code></pre></td></tr></table></figure>

<p><img src="https://yechen-blog-image.oss-cn-hangzhou.aliyuncs.com/images/image-20211020213226914.png" srcset="/img/loading.gif" lazyload alt="错误信息"></p>
<h3 id="2-choose（when、otherwise）"><a href="#2-choose（when、otherwise）" class="headerlink" title="2. choose（when、otherwise）"></a>2. choose（when、otherwise）</h3><p>这个作用和 if 标签类似，也是符合条件才拼接 sql 语句，但是按照顺序只要有一个条件成立，别的条件都不会在判断，可以 java 中的 switch 语句类似</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs java">&lt;select id=<span class="hljs-string">&quot;getStudentByConditionChoose&quot;</span> resultType=<span class="hljs-string">&quot;student&quot;</span>&gt;<br>    select * from student where<br>    &lt;choose&gt;<br>    &lt;when test=<span class="hljs-string">&quot;id != null&quot;</span>&gt;<br>    id=#&#123;id&#125;<br>&lt;/when&gt;<br>    &lt;when test=<span class="hljs-string">&quot;stuName != null and stuName != &#x27;&#x27;&quot;</span>&gt;<br>    stu_name like #&#123;stuName&#125;<br>&lt;/when&gt;<br>    &lt;otherwise&gt;<br>    email=#&#123;email&#125;<br>&lt;/otherwise&gt;<br>    &lt;/choose&gt;<br>    &lt;/select&gt;<br></code></pre></td></tr></table></figure>

<p>不足之处和 if 也是一样是，对于多出的 and 或 or 没有办法处理</p>
<h3 id="3-trim、where、set"><a href="#3-trim、where、set" class="headerlink" title="3. trim、where、set"></a>3. trim、where、set</h3><p>可以解决之前留下的问题，清理掉多出的 and 或 or</p>
<p><strong>where</strong></p>
<p>where 标签中可以包含多个 <code>&lt;if&gt;</code> 标签，当 if 标签中有一个及以上的条件成立时，mybatis 会在 sql 语句后加一个 where 关键字并去掉（添加）条件成立的 if 标签 sql 语句中<strong>开头</strong>多余（需要）的 and 或者 or。</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">select</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;getStudentByConditionWhere&quot;</span> <span class="hljs-attr">resultType</span>=<span class="hljs-string">&quot;student&quot;</span>&gt;</span><br>    select * from student<br>    <span class="hljs-tag">&lt;<span class="hljs-name">where</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">if</span> <span class="hljs-attr">test</span>=<span class="hljs-string">&quot;id != null&quot;</span>&gt;</span><br>            id=#&#123;id&#125;<br>        <span class="hljs-tag">&lt;/<span class="hljs-name">if</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">if</span> <span class="hljs-attr">test</span>=<span class="hljs-string">&quot;stuName != null and stuName != &#x27;&#x27;&quot;</span>&gt;</span><br>            and stu_name like #&#123;stuName&#125;<br>        <span class="hljs-tag">&lt;/<span class="hljs-name">if</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">if</span> <span class="hljs-attr">test</span>=<span class="hljs-string">&quot;email != null and email.trim() != &#x27;&#x27;&quot;</span>&gt;</span><br>            and email=#&#123;email&#125;<br>        <span class="hljs-tag">&lt;/<span class="hljs-name">if</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">if</span> <span class="hljs-attr">test</span>=<span class="hljs-string">&quot;age != null and age &gt; 0&quot;</span>&gt;</span><br>            and age=#&#123;age&#125;<br>        <span class="hljs-tag">&lt;/<span class="hljs-name">if</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">where</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">select</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p>测试</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Test</span><br><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">testWhere</span><span class="hljs-params">()</span> </span>&#123;<br>    SqlSession sqlSession = MyBatisUtils.getSqlSession();<br>    StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);<br>    List&lt;Student&gt; studentList = mapper.getStudentByConditionIf(<span class="hljs-keyword">new</span> Student(<span class="hljs-keyword">null</span>, <span class="hljs-string">&quot;zhangsan&quot;</span>, <span class="hljs-keyword">null</span>, <span class="hljs-keyword">null</span>));<br>    studentList.forEach(System.out::println);<br>&#125;<br></code></pre></td></tr></table></figure>

<p><img src="https://yechen-blog-image.oss-cn-hangzhou.aliyuncs.com/images/image-20211020215941999.png" srcset="/img/loading.gif" lazyload alt="测试结果"></p>
<p><strong>set</strong> </p>
<p>set 标签也是类似的，只是用在添加语句中，主要处理了语句中的 <code>,</code> </p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">insert</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;updateStudent&quot;</span>&gt;</span><br>    update student<br>    <span class="hljs-tag">&lt;<span class="hljs-name">set</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">if</span> <span class="hljs-attr">test</span>=<span class="hljs-string">&quot;stuName != null and stuName != &#x27;&#x27;&quot;</span>&gt;</span><br>            stu_name=#&#123;stuName&#125;,<br>        <span class="hljs-tag">&lt;/<span class="hljs-name">if</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">if</span> <span class="hljs-attr">test</span>=<span class="hljs-string">&quot;email != null and email.trim() != &#x27;&#x27;&quot;</span>&gt;</span><br>            email=#&#123;email&#125;,<br>        <span class="hljs-tag">&lt;/<span class="hljs-name">if</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">if</span> <span class="hljs-attr">test</span>=<span class="hljs-string">&quot;age != null and age &gt; 0&quot;</span>&gt;</span><br>            age=#&#123;age&#125;,<br>        <span class="hljs-tag">&lt;/<span class="hljs-name">if</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">if</span> <span class="hljs-attr">test</span>=<span class="hljs-string">&quot;theClass.id != null&quot;</span>&gt;</span><br>            class_id=#&#123;theClass.id&#125;<br>        <span class="hljs-tag">&lt;/<span class="hljs-name">if</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">set</span>&gt;</span><br>    where id=#&#123;id&#125;<br><span class="hljs-tag">&lt;/<span class="hljs-name">insert</span>&gt;</span><br></code></pre></td></tr></table></figure>



<p><strong>trim</strong></p>
<p>对于 where 标签和 set 标签，我们可以使用 trim 标签自定义达到同样的效果</p>
<p><code>trim</code> 标签中有四个属性</p>
<ul>
<li><code>prefix</code>：语句的前缀，像 where 标签的前缀就是 WHERE，set 标签的前缀就是 SET</li>
<li><code>prefixOverrides</code>：指定要额外要忽略的前缀</li>
<li><code>suffix</code>：后缀</li>
<li><code>suffixOverrides</code>：指定要额为要忽略的后缀</li>
</ul>
<p>与 where 等价的：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-comment">&lt;!-- prefixOverrides：通过管道符分隔的文本序列（注意此例中的空格是必要的） --&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">trim</span> <span class="hljs-attr">prefix</span>=<span class="hljs-string">&quot;WHERE&quot;</span> <span class="hljs-attr">prefixOverrides</span>=<span class="hljs-string">&quot;AND |OR &quot;</span>&gt;</span><br>  ...<br><span class="hljs-tag">&lt;/<span class="hljs-name">trim</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p>与 set 等价的：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">trim</span> <span class="hljs-attr">prefix</span>=<span class="hljs-string">&quot;SET&quot;</span> <span class="hljs-attr">suffixOverrides</span>=<span class="hljs-string">&quot;,&quot;</span>&gt;</span><br>  ...<br><span class="hljs-tag">&lt;/<span class="hljs-name">trim</span>&gt;</span><br></code></pre></td></tr></table></figure>



<h3 id="4-foreach"><a href="#4-foreach" class="headerlink" title="4. foreach"></a>4. foreach</h3><p><strong>用来循环遍历查询条件中的数组、list 集合的，主要用在 sql 语句的 in 语句中</strong></p>
<p><strong>基础语句</strong></p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">foreach</span> <span class="hljs-attr">collection</span>=<span class="hljs-string">&quot;&quot;</span> <span class="hljs-attr">item</span>=<span class="hljs-string">&quot;&quot;</span> <span class="hljs-attr">open</span>=<span class="hljs-string">&quot;&quot;</span> <span class="hljs-attr">close</span>=<span class="hljs-string">&quot;&quot;</span> <span class="hljs-attr">separator</span>=<span class="hljs-string">&quot;&quot;</span> <span class="hljs-attr">index</span>=<span class="hljs-string">&quot;&quot;</span>&gt;</span><br>    #&#123;item中自定义的编历对象.对应的属性值&#125;<br><span class="hljs-tag">&lt;/<span class="hljs-name">foreach</span>&gt;</span><br><span class="hljs-comment">&lt;!--</span><br><span class="hljs-comment">1. collection：表示接口中方法参数的类型，如果是数组，属性值就是 “array”，如果是集合，属性值就是 “list”</span><br><span class="hljs-comment">2. item：自定义的，代表数组或集合成员中的一个变量。</span><br><span class="hljs-comment">3. open：循环开始时的字符。</span><br><span class="hljs-comment">4. close：循环结束时的字符。</span><br><span class="hljs-comment">5. separator：集合成员之间的分隔符。</span><br><span class="hljs-comment">6. index：如果是数组和集合，代表当前数据的索引，如果是 map，就代表当前 map 的 key</span><br><span class="hljs-comment">--&gt;</span><br></code></pre></td></tr></table></figure>

<p><code>collection</code> 属性中指定传递进来的数据，可以填的值有</p>
<ul>
<li><strong>当只有一个数据的时候</strong>：<ul>
<li>集合就使用 <strong>list/arg0/collection</strong>，数组就使用 <strong>array/arg0</strong></li>
<li><strong>不能直接使用接口中的参数名称</strong>，也不可以使用任意名称</li>
<li>如果想使用参数名，需要在接口方法中使用 <code>@Param</code> 注解为当前参数指定名称</li>
</ul>
</li>
<li><strong>当有多个数据的时候</strong><ul>
<li>指定参数数据别名</li>
<li>arg0、arg1、arg2……</li>
<li>param1、param2、param3……</li>
</ul>
</li>
<li><strong>当传递的数据是一个 map 的时候</strong><ul>
<li>map 中的 key</li>
</ul>
</li>
</ul>
<p><strong>查询</strong></p>
<p>参数是一个 list</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">// mapper 接口方法</span><br><span class="hljs-function">List&lt;Student&gt; <span class="hljs-title">getStudentListByIds</span><span class="hljs-params">(List&lt;Integer&gt; ids)</span></span>;<br></code></pre></td></tr></table></figure>

<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-comment">&lt;!-- foreach 查询 --&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">select</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;getStudentListByIds&quot;</span> <span class="hljs-attr">resultType</span>=<span class="hljs-string">&quot;student&quot;</span>&gt;</span><br>    select * from student where id in<br>    <span class="hljs-tag">&lt;<span class="hljs-name">foreach</span> <span class="hljs-attr">collection</span>=<span class="hljs-string">&quot;list&quot;</span> <span class="hljs-attr">item</span>=<span class="hljs-string">&quot;id&quot;</span> <span class="hljs-attr">separator</span>=<span class="hljs-string">&quot;,&quot;</span> <span class="hljs-attr">open</span>=<span class="hljs-string">&quot;(&quot;</span> <span class="hljs-attr">close</span>=<span class="hljs-string">&quot;)&quot;</span>&gt;</span><br>        #&#123;id&#125;<br>    <span class="hljs-tag">&lt;/<span class="hljs-name">foreach</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">select</span>&gt;</span><br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Test</span><br><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">testForeachList</span><span class="hljs-params">()</span> </span>&#123;<br>    SqlSession sqlSession = MyBatisUtils.getSqlSession();<br>    StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);<br>    List&lt;Student&gt; studentList = mapper.getStudentListByIds(Arrays.asList(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>));<br>    studentList.forEach(System.out::println);<br>&#125;<br></code></pre></td></tr></table></figure>



<p>参数是一个 map</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">// mapper 接口方法</span><br><span class="hljs-function">List&lt;Student&gt; <span class="hljs-title">getStudentListByIdMap</span><span class="hljs-params">(Map&lt;String, Object&gt; map)</span></span>;<br></code></pre></td></tr></table></figure>

<p><code>collection</code> 中指定 map 中的 key</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-comment">&lt;!-- foreach 查询 --&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">select</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;getStudentListByIdMap&quot;</span> <span class="hljs-attr">resultType</span>=<span class="hljs-string">&quot;student&quot;</span>&gt;</span><br>    select * from student where id in<br>    <span class="hljs-tag">&lt;<span class="hljs-name">foreach</span> <span class="hljs-attr">collection</span>=<span class="hljs-string">&quot;ids&quot;</span> <span class="hljs-attr">item</span>=<span class="hljs-string">&quot;id&quot;</span> <span class="hljs-attr">separator</span>=<span class="hljs-string">&quot;,&quot;</span> <span class="hljs-attr">open</span>=<span class="hljs-string">&quot;(&quot;</span> <span class="hljs-attr">close</span>=<span class="hljs-string">&quot;)&quot;</span>&gt;</span><br>        #&#123;id&#125;<br>    <span class="hljs-tag">&lt;/<span class="hljs-name">foreach</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">select</span>&gt;</span><br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Test</span><br><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">testForeachMap</span><span class="hljs-params">()</span> </span>&#123;<br>    SqlSession sqlSession = MyBatisUtils.getSqlSession();<br>    StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);<br>    Map&lt;String, Object&gt; map = <span class="hljs-keyword">new</span> HashMap&lt;&gt;();<br>    map.put(<span class="hljs-string">&quot;1&quot;</span>, <span class="hljs-number">1</span>);<br>    map.put(<span class="hljs-string">&quot;ids&quot;</span>, Arrays.asList(<span class="hljs-number">1</span>,<span class="hljs-number">2</span>,<span class="hljs-number">3</span>));<br>    List&lt;Student&gt; studentList = mapper.getStudentListByIdMap(map);<br>    studentList.forEach(System.out::println);<br>&#125;<br></code></pre></td></tr></table></figure>



<p><strong>批量插入</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">// mapper 接口方法</span><br><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">batchInsertStudent</span><span class="hljs-params">(List&lt;Student&gt; studentList)</span></span>;<br></code></pre></td></tr></table></figure>

<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-comment">&lt;!-- foreach 批量插入 --&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">insert</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;batchInsertStudent&quot;</span> &gt;</span><br>    insert into student (stu_name, email, age, class_id) values<br>    <span class="hljs-tag">&lt;<span class="hljs-name">foreach</span> <span class="hljs-attr">collection</span>=<span class="hljs-string">&quot;list&quot;</span> <span class="hljs-attr">item</span>=<span class="hljs-string">&quot;student&quot;</span> <span class="hljs-attr">separator</span>=<span class="hljs-string">&quot;,&quot;</span> &gt;</span><br>        (#&#123;student.stuName&#125;, #&#123;student.email&#125;, #&#123;student.age&#125;, #&#123;student.theClass.id&#125;)<br>    <span class="hljs-tag">&lt;/<span class="hljs-name">foreach</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">insert</span>&gt;</span><br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Test</span><br><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">testBatchInsert</span><span class="hljs-params">()</span> </span>&#123;<br>    SqlSession sqlSession = MyBatisUtils.getSqlSession();<br>    StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);<br>    List&lt;Student&gt; studentList = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();<br>    studentList.add(<span class="hljs-keyword">new</span> Student(<span class="hljs-keyword">null</span>, <span class="hljs-string">&quot;yechen&quot;</span>, <span class="hljs-string">&quot;yechen@qq.com&quot;</span>, <span class="hljs-number">20</span>, <span class="hljs-keyword">new</span> TheClass(<span class="hljs-number">1</span>, <span class="hljs-string">&quot;高三一班&quot;</span>, <span class="hljs-string">&quot;tom&quot;</span>)));<br>    studentList.add(<span class="hljs-keyword">new</span> Student(<span class="hljs-keyword">null</span>, <span class="hljs-string">&quot;chenwenqi&quot;</span>, <span class="hljs-string">&quot;chenwenqi@qq.com&quot;</span>, <span class="hljs-number">18</span>, <span class="hljs-keyword">new</span> TheClass(<span class="hljs-number">2</span>, <span class="hljs-string">&quot;高三二班&quot;</span>, <span class="hljs-string">&quot;jack&quot;</span>)));<br>    mapper.batchInsertStudent(studentList);<br>&#125;<br></code></pre></td></tr></table></figure>

<p><img src="https://yechen-blog-image.oss-cn-hangzhou.aliyuncs.com/images/image-20211026161135967.png" srcset="/img/loading.gif" lazyload alt="测试结果"></p>
<h3 id="5-bind"><a href="#5-bind" class="headerlink" title="5. bind"></a>5. bind</h3><p>bind 元素可以从 OGNL 表达式中创建一个变量并将其绑定到上下文，例如要实现模糊查询</p>
<p>通过名字模糊查询</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">// mapper 接口方法</span><br><span class="hljs-function">List&lt;Student&gt; <span class="hljs-title">getStudentListByName</span><span class="hljs-params">(String name)</span></span>;<br></code></pre></td></tr></table></figure>

<p>bind 标签中，value 对应接口方法传递进来的数据，name 属性给对应字段取的变量名。</p>
<p><strong>在 value 属性中可以使用字符串拼接等特殊处理。</strong></p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">select</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;getStudentListByName&quot;</span> <span class="hljs-attr">resultType</span>=<span class="hljs-string">&quot;student&quot;</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">bind</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;name&quot;</span> <span class="hljs-attr">value</span>=<span class="hljs-string">&quot;&#x27;%&#x27; + name + &#x27;%&#x27;&quot;</span>/&gt;</span><br>    select * from student where stu_name like #&#123;name&#125;<br><span class="hljs-tag">&lt;/<span class="hljs-name">select</span>&gt;</span><br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Test</span><br><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">testBind</span><span class="hljs-params">()</span> </span>&#123;<br>    SqlSession sqlSession = MyBatisUtils.getSqlSession();<br>    StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);<br>    List&lt;Student&gt; studentList = mapper.getStudentListByName(<span class="hljs-string">&quot;e&quot;</span>);<br>    studentList.forEach(System.out::println);<br>&#125;<br></code></pre></td></tr></table></figure>

<p><img src="https://yechen-blog-image.oss-cn-hangzhou.aliyuncs.com/images/image-20211026162351092.png" srcset="/img/loading.gif" lazyload alt="测试结果"></p>
<h3 id="6-两个内置对象"><a href="#6-两个内置对象" class="headerlink" title="6. 两个内置对象"></a>6. 两个内置对象</h3><p><strong>_parameter</strong>：代表接口方法传递过来的整个参数</p>
<ul>
<li>单个参数：_parameter就是这个参数</li>
<li>多个参数：参数会被封装为一个map，_parameter 就是代表这个 map</li>
</ul>
<p><strong>_databaseId</strong>（多数据库支持）</p>
<ul>
<li><p>如果配置了 databaseIdProvider 标签，_databaseId 就是代表当前数据库的别名</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">select</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;&quot;</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">if</span> <span class="hljs-attr">test</span>=<span class="hljs-string">&quot;_databaseId == &#x27;mysql&#x27;&quot;</span>&gt;</span><br>        <br>    <span class="hljs-tag">&lt;/<span class="hljs-name">if</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">if</span> <span class="hljs-attr">test</span>=<span class="hljs-string">&quot;_databaseId == &#x27;oracle&#x27;&quot;</span>&gt;</span><br>        <br>    <span class="hljs-tag">&lt;/<span class="hljs-name">if</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">select</span>&gt;</span><br></code></pre></td></tr></table></figure></li>
</ul>
<h3 id="7-sql-标签"><a href="#7-sql-标签" class="headerlink" title="7. sql 标签"></a>7. sql 标签</h3><p>将高复用的 sql 语句放在 <code>&lt;sql&gt;</code> 标签中，实现 sql 的复用。</p>
<p>使用步骤：</p>
<ol>
<li><p>先定义</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">sql</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;自定义的唯一名称，代表当前 sql&quot;</span>&gt;</span><br>    sql 语句<br><span class="hljs-tag">&lt;/<span class="hljs-name">sql</span>&gt;</span><br></code></pre></td></tr></table></figure></li>
<li><p>在 <code>&lt;select&gt;&lt;insert&gt;</code> 等标签中使用 sql 语句</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">select</span>&gt;</span><br>	<span class="hljs-tag">&lt;<span class="hljs-name">include</span> <span class="hljs-attr">refid</span>=<span class="hljs-string">&quot;sql 标签中 id 的值&quot;</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">select</span>&gt;</span><br></code></pre></td></tr></table></figure></li>
</ol>
<h2 id="六、缓存"><a href="#六、缓存" class="headerlink" title="六、缓存"></a>六、缓存</h2><p>MyBatis 包含一个非常强大的查询缓存特性,它可以非常方便地配置和定制。缓存可以极大的提升查询效率。</p>
<p>在 MyBatis 中存在两级缓存，<strong>一级缓存默认是开启的，二级缓存需要自己开启。</strong></p>
<ul>
<li><p><strong>一级缓存（本地缓存）</strong></p>
<p>sqlSession 级别的缓存，一级缓存是一直开启的，以 map 的形式保存，与数据库同一次会话期间查询到的数据会放在本地缓存中，以后如果需要获取相同的数据，直接从缓存中拿，没必要再去查询数据库</p>
<p><strong>一级缓存失效情况</strong>：</p>
<ul>
<li>sqlSession 不同</li>
<li>sqlSession 相同，查询条件不同</li>
<li>sqlSession 相同，两次查询之间执行了增删改操作（增删改操作会清空缓存）</li>
<li>sqlSession 相同，手动清除了一级缓存（<code>sqlSession.clearCache();</code>）</li>
</ul>
</li>
<li><p><strong>二级缓存（全局缓存）：</strong></p>
<p>基于 namespace 级别的缓存，一个 namespace 对应一个二级缓存</p>
<p><strong>开启设置：</strong></p>
<ul>
<li>开启全局二级缓存配置：<code>&lt;setting name=&quot;cacheEnabled&quot; value=&quot;true&quot;/&gt;</code></li>
<li>去 mapper.xml 中配置使用二级缓存：<code>&lt;cache&gt;&lt;/cache&gt;</code></li>
<li>我们的 POJO 需要<strong>实现序列化接口</strong></li>
</ul>
<p><strong>工作机制：</strong></p>
<ul>
<li><p>一个会话（sqlSession），查询一条数据，这个数据就会被放在当前会话的一级缓存中</p>
</li>
<li><p>如果会话关闭，一级缓存中的数据会被保存到二级缓存中，新的会话查询信息，就可以参照二级缓存中的内容</p>
</li>
<li><p>查出的数据都会被默认先放在一级缓存中，<strong>只有会话提交或者关闭以后，一级缓存中的数据才会转移到二级缓存中</strong></p>
</li>
</ul>
</li>
<li><p><strong>和缓存有关的设置/属性：</strong></p>
<ul>
<li>setting 中的 <code>cacheEnabled=true：false</code> 开启/关闭二级缓存（二级缓存关闭时，一级缓存一直可用的)</li>
<li>mapper.xml 中 <code>&lt;cache&gt;&lt;/cache&gt;</code> 开启二级缓存</li>
<li>每个 select 标签都有 <code>useCache=&quot;true/false&quot;</code>，是否使用二级缓存</li>
<li>每一个增删改查标签都有 <code>flushCache=&quot;true/false&quot;</code>，<code>select</code> 标签默认值为 false，其他标签默认值为 true，设置为 true 后，每次语句执行完成之后，都会清空缓存（一级二级都清空）</li>
<li><code>sqlSession.clearCache()</code>，只是清除当前 sqlSession 的一级缓存</li>
<li>setting 中的 <code>localCacheScope</code> 设置，本地缓存作用域，默认值是 <code>SESSION</code>，即当前会话的所有数据保存在会话缓存中，可以设置为 <code>STATEMENT</code> 禁用一级缓存</li>
</ul>
</li>
</ul>
<h3 id="使用缓存"><a href="#使用缓存" class="headerlink" title="使用缓存"></a>使用缓存</h3><p><a target="_blank" rel="noopener" href="https://blog.csdn.net/weixin_37139197/article/details/82908377">使用缓存</a></p>
<h3 id="使用-ehcache-做缓存"><a href="#使用-ehcache-做缓存" class="headerlink" title="使用 ehcache 做缓存"></a>使用 ehcache 做缓存</h3><p><a target="_blank" rel="noopener" href="http://mybatis.org/ehcache-cache/">官方文档</a></p>
<p><strong>ehcaceh.xml 文件：</strong></p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">ehcache</span> <span class="hljs-attr">xmlns:xsi</span>=<span class="hljs-string">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span></span><br><span class="hljs-tag">         <span class="hljs-attr">xsi:noNamespaceSchemaLocation</span>=<span class="hljs-string">&quot;http://ehcache.org/ehcache.xsd&quot;</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">diskStore</span> <span class="hljs-attr">path</span>=<span class="hljs-string">&quot;D:\&quot;</span> /&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">defaultCache</span></span><br><span class="hljs-tag">            <span class="hljs-attr">maxElementsInMemory</span>=<span class="hljs-string">&quot;10000&quot;</span></span><br><span class="hljs-tag">            <span class="hljs-attr">eternal</span>=<span class="hljs-string">&quot;true&quot;</span></span><br><span class="hljs-tag">            <span class="hljs-attr">timeToIdleSeconds</span>=<span class="hljs-string">&quot;120&quot;</span></span><br><span class="hljs-tag">            <span class="hljs-attr">timeToLiveSeconds</span>=<span class="hljs-string">&quot;120&quot;</span></span><br><span class="hljs-tag">            <span class="hljs-attr">overflowToDisk</span>=<span class="hljs-string">&quot;true&quot;</span></span><br><span class="hljs-tag">            <span class="hljs-attr">maxElementsOnDisk</span>=<span class="hljs-string">&quot;10000000&quot;</span></span><br><span class="hljs-tag">            <span class="hljs-attr">diskPersistent</span>=<span class="hljs-string">&quot;false&quot;</span></span><br><span class="hljs-tag">            <span class="hljs-attr">diskExpiryThreadIntervalSeconds</span>=<span class="hljs-string">&quot;120&quot;</span></span><br><span class="hljs-tag">            <span class="hljs-attr">memoryStoreEvictionPolicy</span>=<span class="hljs-string">&quot;LRU&quot;</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">defaultCache</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">ehcache</span>&gt;</span><br></code></pre></td></tr></table></figure>



<h2 id="七、整合-Spring-SpringMVC"><a href="#七、整合-Spring-SpringMVC" class="headerlink" title="七、整合 Spring+SpringMVC"></a>七、整合 Spring+SpringMVC</h2><p><a target="_blank" rel="noopener" href="https://blog.csdn.net/qq_25233621/article/details/102792862">SSM整合</a></p>
<p><a target="_blank" rel="noopener" href="https://serverless-page-bucket-jg0mi1oc-1304852402.cos-website.ap-hongkong.myqcloud.com/2021/09/13/SSM%E6%A1%86%E6%9E%B6-2021-09-13-Spring/#8-Spring-%E9%9B%86%E6%88%90-MyBatis">Spring整合MyBatis</a></p>
<p><a target="_blank" rel="noopener" href="https://yechen-blog-image.oss-cn-hangzhou.aliyuncs.com/file/applicationContext.xml">Spring配置文件</a></p>
<p><a target="_blank" rel="noopener" href="https://yechen-blog-image.oss-cn-hangzhou.aliyuncs.com/file/springmvc.xml">SpringMVC配置文件</a></p>
<p><a target="_blank" rel="noopener" href="https://yechen-blog-image.oss-cn-hangzhou.aliyuncs.com/file/mybatis-config.xml">MyBatis配置文件</a></p>
<h2 id="八、逆向工程"><a href="#八、逆向工程" class="headerlink" title="八、逆向工程"></a>八、逆向工程</h2><p>generatorConfig.xml</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-meta">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span><br><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">generatorConfiguration</span> <span class="hljs-meta-keyword">PUBLIC</span> <span class="hljs-meta-string">&quot;-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN&quot;</span> <span class="hljs-meta-string">&quot;http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd&quot;</span>&gt;</span><br><br><span class="hljs-tag">&lt;<span class="hljs-name">generatorConfiguration</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">context</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;DB2Tables&quot;</span> <span class="hljs-attr">targetRuntime</span>=<span class="hljs-string">&quot;MyBatis3&quot;</span>&gt;</span><br><br>        <span class="hljs-tag">&lt;<span class="hljs-name">commentGenerator</span>&gt;</span><br>            <span class="hljs-comment">&lt;!-- 是否去除自动生成的注释 --&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;suppressAllComments&quot;</span> <span class="hljs-attr">value</span>=<span class="hljs-string">&quot;true&quot;</span>/&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">commentGenerator</span>&gt;</span><br><br>        <span class="hljs-comment">&lt;!-- Mysql数据库连接的信息：驱动类、连接地址、用户名、密码 --&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">jdbcConnection</span> <span class="hljs-attr">driverClass</span>=<span class="hljs-string">&quot;com.mysql.cj.jdbc.Driver&quot;</span></span><br><span class="hljs-tag">                        <span class="hljs-attr">connectionURL</span>=<span class="hljs-string">&quot;jdbc:mysql://localhost:3306/mybatis&quot;</span></span><br><span class="hljs-tag">                        <span class="hljs-attr">userId</span>=<span class="hljs-string">&quot;root&quot;</span></span><br><span class="hljs-tag">                        <span class="hljs-attr">password</span>=<span class="hljs-string">&quot;123456&quot;</span>&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">jdbcConnection</span>&gt;</span><br><br>        <span class="hljs-comment">&lt;!-- 默认为false，把JDBC DECIMAL 和NUMERIC类型解析为Integer，为true时</span><br><span class="hljs-comment">        把JDBC DECIMAL 和NUMERIC类型解析为java.math.BigDecimal --&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">javaTypeResolver</span> &gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;forceBigDecimals&quot;</span> <span class="hljs-attr">value</span>=<span class="hljs-string">&quot;false&quot;</span> /&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">javaTypeResolver</span>&gt;</span><br><br>        <span class="hljs-comment">&lt;!-- targetProject：生成POJO类的位置 --&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">javaModelGenerator</span> <span class="hljs-attr">targetPackage</span>=<span class="hljs-string">&quot;cn.yechen.pojo&quot;</span> <span class="hljs-attr">targetProject</span>=<span class="hljs-string">&quot;.\src\main\java&quot;</span>&gt;</span><br>            <span class="hljs-comment">&lt;!-- enableSubPackages:是否让schema作为包的后缀 --&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;enableSubPackages&quot;</span> <span class="hljs-attr">value</span>=<span class="hljs-string">&quot;false&quot;</span> /&gt;</span><br>            <span class="hljs-comment">&lt;!-- 从数据库返回的值被清理前后的空格 --&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;trimStrings&quot;</span> <span class="hljs-attr">value</span>=<span class="hljs-string">&quot;true&quot;</span> /&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">javaModelGenerator</span>&gt;</span><br><br>        <span class="hljs-comment">&lt;!-- targetProject：mapper映射文件生成的位置 --&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">sqlMapGenerator</span> <span class="hljs-attr">targetPackage</span>=<span class="hljs-string">&quot;mybatis.mapper&quot;</span>  <span class="hljs-attr">targetProject</span>=<span class="hljs-string">&quot;.\src\main\resources&quot;</span>&gt;</span><br>            <span class="hljs-comment">&lt;!-- enableSubPackages:是否让schema作为包的后缀 --&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;enableSubPackages&quot;</span> <span class="hljs-attr">value</span>=<span class="hljs-string">&quot;false&quot;</span> /&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">sqlMapGenerator</span>&gt;</span><br><br>        <span class="hljs-comment">&lt;!-- targetProject：mapper接口生成的的位置 --&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">javaClientGenerator</span> <span class="hljs-attr">type</span>=<span class="hljs-string">&quot;XMLMAPPER&quot;</span> <span class="hljs-attr">targetPackage</span>=<span class="hljs-string">&quot;cn.yechen.mapper&quot;</span>  <span class="hljs-attr">targetProject</span>=<span class="hljs-string">&quot;.\src\main\java&quot;</span>&gt;</span><br>            <span class="hljs-comment">&lt;!-- enableSubPackages:是否让schema作为包的后缀 --&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;enableSubPackages&quot;</span> <span class="hljs-attr">value</span>=<span class="hljs-string">&quot;false&quot;</span> /&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">javaClientGenerator</span>&gt;</span><br><br>        <span class="hljs-comment">&lt;!-- 指定数据表 --&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">table</span> <span class="hljs-attr">tableName</span>=<span class="hljs-string">&quot;student&quot;</span> <span class="hljs-attr">domainObjectName</span>=<span class="hljs-string">&quot;Student&quot;</span>/&gt;</span><br><br>        <span class="hljs-comment">&lt;!-- 有些表的字段需要指定java类型</span><br><span class="hljs-comment">        &lt;table schema=&quot;DB2ADMIN&quot; tableName=&quot;ALLTYPES&quot; domainObjectName=&quot;Customer&quot; &gt;</span><br><span class="hljs-comment">          &lt;property name=&quot;useActualColumnNames&quot; value=&quot;true&quot;/&gt;</span><br><span class="hljs-comment">          &lt;generatedKey column=&quot;ID&quot; sqlStatement=&quot;DB2&quot; identity=&quot;true&quot; /&gt;</span><br><span class="hljs-comment">          &lt;columnOverride column=&quot;DATE_FIELD&quot; property=&quot;startDate&quot; /&gt;</span><br><span class="hljs-comment">          &lt;ignoreColumn column=&quot;FRED&quot; /&gt;</span><br><span class="hljs-comment">          &lt;columnOverride column=&quot;LONG_VARCHAR_FIELD&quot; jdbcType=&quot;VARCHAR&quot; /&gt;</span><br><span class="hljs-comment">        &lt;/table&gt; --&gt;</span><br><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">context</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">generatorConfiguration</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p>自己写代码来逆向生成代码：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyBatisGeneratorTest</span> </span>&#123;<br><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> <span class="hljs-keyword">throws</span> Exception </span>&#123;<br>        List&lt;String&gt; warnings = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();<br>        <span class="hljs-keyword">boolean</span> overwrite = <span class="hljs-keyword">true</span>;<br>        File configFile = <span class="hljs-keyword">new</span> File(<span class="hljs-string">&quot;generatorConfig.xml&quot;</span>);<br>        ConfigurationParser cp = <span class="hljs-keyword">new</span> ConfigurationParser(warnings);<br>        Configuration config = cp.parseConfiguration(configFile);<br>        DefaultShellCallback callback = <span class="hljs-keyword">new</span> DefaultShellCallback(overwrite);<br>        MyBatisGenerator myBatisGenerator = <span class="hljs-keyword">new</span> MyBatisGenerator(config, callback, warnings);<br>        myBatisGenerator.generate(<span class="hljs-keyword">null</span>);<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<p>通过 maven 插件来生成代码</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">plugin</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.mybatis.generator<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>mybatis-generator-maven-plugin<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>1.4.0<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">dependencies</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>mysql<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>mysql-connector-java<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>8.0.26<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">dependencies</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">configuration</span>&gt;</span><br>        <span class="hljs-comment">&lt;!--配置文件的路径--&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">configurationFile</span>&gt;</span>generatorConfig.xml<span class="hljs-tag">&lt;/<span class="hljs-name">configurationFile</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">overwrite</span>&gt;</span>true<span class="hljs-tag">&lt;/<span class="hljs-name">overwrite</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">configuration</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">plugin</span>&gt;</span><br></code></pre></td></tr></table></figure>



<p><a target="_blank" rel="noopener" href="https://www.cnblogs.com/zzjlxy-225223/p/12458344.html">IDEA-MyBatis逆向工程的使用</a></p>
<h2 id="九、运行原理"><a href="#九、运行原理" class="headerlink" title="九、运行原理"></a>九、运行原理</h2><p><img src="https://yechen-blog-image.oss-cn-hangzhou.aliyuncs.com/images/image-20211028094149653.png" srcset="/img/loading.gif" lazyload alt="mybatis运行原理图"></p>
<h3 id="创建-SqlSessionFactory"><a href="#创建-SqlSessionFactory" class="headerlink" title="创建 SqlSessionFactory"></a>创建 SqlSessionFactory</h3><p><strong>工作流程：</strong></p>
<ol>
<li>读取配置文件生成输入流</li>
<li>创建 <code>SqlSessionFactoryBuilder</code>，通过其 build(inputStream) 方法创建 SqlSessionFactory 对象<ol>
<li>创建代码解析器 <code>XMLConfigBuilder</code> 对象，使用其 <code>parse()</code> 方法解析配置文件并生成 <code>Configuration </code>对象<strong>并返回</strong>，该对象中保存了配置文件中的所有信息<ul>
<li><strong>其中重要一步</strong>：解析 mappers 标签，提取 mapper 映射文件，将其中的每一个增删改查标签都封装成一个 <code>MappedStatement</code> 对象并存入 Configuration 对象中</li>
<li>每一个 Mapper 接口对应一个 <code>MapperProxyFactory</code>，保存在 Configuration 对象中的 MapperRegistry 属性中</li>
</ul>
</li>
<li><code>SqlSessionFactoryBuilder</code> 通过 build() 方法传入 Configuration 对象生成 SqlSessionFactory（<code>DefaultSqlSessionFactory</code> 类型）</li>
</ol>
</li>
</ol>
<p><strong>Configuration 对象中的重要属性</strong></p>
<p><img src="https://yechen-blog-image.oss-cn-hangzhou.aliyuncs.com/images/image-20211028105012091.png" srcset="/img/loading.gif" lazyload alt="MappedStatement"></p>
<p><img src="https://yechen-blog-image.oss-cn-hangzhou.aliyuncs.com/images/image-20211028104840898.png" srcset="/img/loading.gif" lazyload alt="MapperRegistry"></p>
<p><strong>时序图：</strong></p>
<p><img src="https://yechen-blog-image.oss-cn-hangzhou.aliyuncs.com/images/image-20211027222745828.png" srcset="/img/loading.gif" lazyload alt="创建 SqlSessionFactory 时序图"></p>
<p><strong>代码摘要：</strong></p>
<ol>
<li>调用 build 方法<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs java">SqlSessionFactoryBuilder sqlSessionFactoryBuilder = <span class="hljs-keyword">new</span> SqlSessionFactoryBuilder();<br>SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);<br></code></pre></td></tr></table></figure></li>
<li>sqlSessionFactoryBuilder 对象的 build 方法，内部创建解析器，最终返回 DefaultSqlSessionFactory<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-function"><span class="hljs-keyword">public</span> SqlSessionFactory <span class="hljs-title">build</span><span class="hljs-params">(InputStream inputStream, String environment, Properties properties)</span> </span>&#123;<br>  <span class="hljs-keyword">try</span> &#123;<br>    <span class="hljs-comment">// 创建解析器 parser</span><br>    XMLConfigBuilder parser = <span class="hljs-keyword">new</span> XMLConfigBuilder(inputStream, environment, properties);<br>    <span class="hljs-keyword">return</span> build(parser.parse());<br>  &#125;<br>&#125;<br></code></pre></td></tr></table></figure></li>
<li>解析器解析配置文件<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-function"><span class="hljs-keyword">public</span> Configuration <span class="hljs-title">parse</span><span class="hljs-params">()</span> </span>&#123;<br>  parsed = <span class="hljs-keyword">true</span>;<br>  parseConfiguration(parser.evalNode(<span class="hljs-string">&quot;/configuration&quot;</span>));<br>  <span class="hljs-keyword">return</span> configuration;<br>&#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">// 解析一系列配置</span><br><span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">parseConfiguration</span><span class="hljs-params">(XNode root)</span> </span>&#123;<br>  <span class="hljs-keyword">try</span> &#123;<br>    <span class="hljs-comment">// issue #117 read properties first</span><br>    propertiesElement(root.evalNode(<span class="hljs-string">&quot;properties&quot;</span>));<br>    Properties settings = settingsAsProperties(root.evalNode(<span class="hljs-string">&quot;settings&quot;</span>));<br>    loadCustomVfs(settings);<br>    loadCustomLogImpl(settings);<br>    typeAliasesElement(root.evalNode(<span class="hljs-string">&quot;typeAliases&quot;</span>));<br>    pluginElement(root.evalNode(<span class="hljs-string">&quot;plugins&quot;</span>));<br>    objectFactoryElement(root.evalNode(<span class="hljs-string">&quot;objectFactory&quot;</span>));<br>    objectWrapperFactoryElement(root.evalNode(<span class="hljs-string">&quot;objectWrapperFactory&quot;</span>));<br>    reflectorFactoryElement(root.evalNode(<span class="hljs-string">&quot;reflectorFactory&quot;</span>));<br>    settingsElement(settings);<br>    <span class="hljs-comment">// read it after objectFactory and objectWrapperFactory issue #631</span><br>    environmentsElement(root.evalNode(<span class="hljs-string">&quot;environments&quot;</span>));<br>    databaseIdProviderElement(root.evalNode(<span class="hljs-string">&quot;databaseIdProvider&quot;</span>));<br>    typeHandlerElement(root.evalNode(<span class="hljs-string">&quot;typeHandlers&quot;</span>));<br>    mapperElement(root.evalNode(<span class="hljs-string">&quot;mappers&quot;</span>));<br>  &#125; <span class="hljs-keyword">catch</span> (Exception e) &#123;<br>    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> BuilderException(<span class="hljs-string">&quot;Error parsing SQL Mapper Configuration. Cause: &quot;</span> + e, e);<br>  &#125;<br>&#125;<br></code></pre></td></tr></table></figure></li>
<li>解析器解析 mappers 标签<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">// 解析 mappers 标签</span><br><span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">mapperElement</span><span class="hljs-params">(XNode parent)</span> <span class="hljs-keyword">throws</span> Exception </span>&#123;<br>  <span class="hljs-keyword">if</span> (parent != <span class="hljs-keyword">null</span>) &#123;<br>    <span class="hljs-keyword">for</span> (XNode child : parent.getChildren()) &#123;<br>      <span class="hljs-keyword">if</span> (<span class="hljs-string">&quot;package&quot;</span>.equals(child.getName())) &#123;<br>        String mapperPackage = child.getStringAttribute(<span class="hljs-string">&quot;name&quot;</span>);<br>        configuration.addMappers(mapperPackage);<br>      &#125; <span class="hljs-keyword">else</span> &#123;<br>        String resource = child.getStringAttribute(<span class="hljs-string">&quot;resource&quot;</span>);<br>        String url = child.getStringAttribute(<span class="hljs-string">&quot;url&quot;</span>);<br>        String mapperClass = child.getStringAttribute(<span class="hljs-string">&quot;class&quot;</span>);<br>        <span class="hljs-keyword">if</span> (resource != <span class="hljs-keyword">null</span> &amp;&amp; url == <span class="hljs-keyword">null</span> &amp;&amp; mapperClass == <span class="hljs-keyword">null</span>) &#123;<br>          ErrorContext.instance().resource(resource);<br>          <span class="hljs-keyword">try</span>(InputStream inputStream = Resources.getResourceAsStream(resource)) &#123;<br>            XMLMapperBuilder mapperParser = <span class="hljs-keyword">new</span> XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());<br>            <span class="hljs-comment">// 解析 mapper 映射文件  </span><br>            mapperParser.parse();<br>          &#125;<br>        &#125;<br>      &#125;<br>    &#125;<br>  &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">parse</span><span class="hljs-params">()</span> </span>&#123;<br>  <span class="hljs-keyword">if</span> (!configuration.isResourceLoaded(resource)) &#123;<br>    <span class="hljs-comment">// 解析 mapper 映射文件中的 mapper 标签</span><br>    configurationElement(parser.evalNode(<span class="hljs-string">&quot;/mapper&quot;</span>));<br>    configuration.addLoadedResource(resource);<br>    bindMapperForNamespace();<br>  &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">configurationElement</span><span class="hljs-params">(XNode context)</span> </span>&#123;<br>  <span class="hljs-keyword">try</span> &#123;<br>    String namespace = context.getStringAttribute(<span class="hljs-string">&quot;namespace&quot;</span>);<br>    <span class="hljs-keyword">if</span> (namespace == <span class="hljs-keyword">null</span> || namespace.isEmpty()) &#123;<br>      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> BuilderException(<span class="hljs-string">&quot;Mapper&#x27;s namespace cannot be empty&quot;</span>);<br>    &#125;<br>    builderAssistant.setCurrentNamespace(namespace);<br>    cacheRefElement(context.evalNode(<span class="hljs-string">&quot;cache-ref&quot;</span>));<br>    cacheElement(context.evalNode(<span class="hljs-string">&quot;cache&quot;</span>));<br>    parameterMapElement(context.evalNodes(<span class="hljs-string">&quot;/mapper/parameterMap&quot;</span>));<br>    resultMapElements(context.evalNodes(<span class="hljs-string">&quot;/mapper/resultMap&quot;</span>));<br>    sqlElement(context.evalNodes(<span class="hljs-string">&quot;/mapper/sql&quot;</span>));<br>    <span class="hljs-comment">// 解析增删改查标签，创建对应对象  </span><br>    buildStatementFromContext(context.evalNodes(<span class="hljs-string">&quot;select|insert|update|delete&quot;</span>));<br>  &#125; <span class="hljs-keyword">catch</span> (Exception e) &#123;<br>    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> BuilderException(<span class="hljs-string">&quot;Error parsing Mapper XML. The XML location is &#x27;&quot;</span> + resource + <span class="hljs-string">&quot;&#x27;. Cause: &quot;</span> + e, e);<br>  &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">buildStatementFromContext</span><span class="hljs-params">(List&lt;XNode&gt; list)</span> </span>&#123;<br>  <span class="hljs-keyword">if</span> (configuration.getDatabaseId() != <span class="hljs-keyword">null</span>) &#123;<br>    buildStatementFromContext(list, configuration.getDatabaseId());<br>  &#125;<br>  buildStatementFromContext(list, <span class="hljs-keyword">null</span>);<br>&#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">buildStatementFromContext</span><span class="hljs-params">(List&lt;XNode&gt; list, String requiredDatabaseId)</span> </span>&#123;<br>  <span class="hljs-keyword">for</span> (XNode context : list) &#123;<br>    <span class="hljs-keyword">final</span> XMLStatementBuilder statementParser = <span class="hljs-keyword">new</span> XMLStatementBuilder(configuration, builderAssistant, context, requiredDatabaseId);<br>    <span class="hljs-keyword">try</span> &#123;<br>      statementParser.parseStatementNode();<br>    &#125; <span class="hljs-keyword">catch</span> (IncompleteElementException e) &#123;<br>      configuration.addIncompleteStatement(statementParser);<br>    &#125;<br>  &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">parseStatementNode</span><span class="hljs-params">()</span> </span>&#123;<br>  <span class="hljs-comment">// 获取一系列的值</span><br><br>  <span class="hljs-comment">// 将这些值封装，创建一个 MappedStatement 对象  </span><br>  builderAssistant.addMappedStatement(id, sqlSource, statementType, sqlCommandType,<br>      fetchSize, timeout, parameterMap, parameterTypeClass, resultMap, resultTypeClass,<br>      resultSetTypeEnum, flushCache, useCache, resultOrdered,<br>      keyGenerator, keyProperty, keyColumn, databaseId, langDriver, resultSets);<br>&#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-function"><span class="hljs-keyword">public</span> MappedStatement <span class="hljs-title">addMappedStatement</span><span class="hljs-params">()</span> </span>&#123;<br>  MappedStatement statement = statementBuilder.build();<br>  <span class="hljs-comment">// 将创建好的 MappedStatement 对象保存到 configuration 对象中  </span><br>  configuration.addMappedStatement(statement);<br>  <span class="hljs-keyword">return</span> statement;<br>&#125;<br></code></pre></td></tr></table></figure></li>
<li>返回 DefaultSqlSessionFactory，其中包含了配置信息 configuration 对象<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-function"><span class="hljs-keyword">public</span> SqlSessionFactory <span class="hljs-title">build</span><span class="hljs-params">(Configuration config)</span> </span>&#123;<br>  <span class="hljs-comment">// 返回 SqlSessionFactory 对象，保存了 configuration</span><br>  <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> DefaultSqlSessionFactory(config);<br>&#125;<br></code></pre></td></tr></table></figure></li>
</ol>
<h3 id="获取-SqlSession"><a href="#获取-SqlSession" class="headerlink" title="获取 SqlSession"></a>获取 SqlSession</h3><p><strong>工作流程：</strong></p>
<ol>
<li>调用 SqlSessionFactory 对象的 openSession() 方法（内部再调用 openSessionFromDataSource() 方法，同时获取<strong>执行器类型</strong>作为参数传递进去）<ol>
<li>从 Configuration 对象中获取一些信息，如环境信息，事务工厂</li>
<li>通过 newExecutor() 方法创建执行器<ol>
<li>通过执行器类型创建不同的执行器<code>BatchExecutor</code> \ <code>ReuseExecutor</code> \ <code>SimpleExecutor</code></li>
<li>如果配置了二级缓存，创建 <code>CachingExecutor</code> 包装当前执行器</li>
<li>如果存在拦截器，便利拦截器继续执行器（<strong>插件使用这个</strong>）</li>
<li>返回执行器（executor）</li>
</ol>
</li>
<li>创建 <code>DefaultSqlSession</code> 对象，传入 <strong>configuration，executor</strong> 等属性</li>
<li>返回 SqlSession 对象</li>
</ol>
</li>
</ol>
<p><strong>时序图：</strong></p>
<p><img src="https://yechen-blog-image.oss-cn-hangzhou.aliyuncs.com/images/image-20211028102053302.png" srcset="/img/loading.gif" lazyload alt="创建 sqlSession 时序图"></p>
<p><strong>代码摘要：</strong></p>
<ol>
<li><p>openSession 方法</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs java">SqlSession sqlSession = sqlSessionFactory.openSession();<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Override</span><br><span class="hljs-function"><span class="hljs-keyword">public</span> SqlSession <span class="hljs-title">openSession</span><span class="hljs-params">()</span> </span>&#123;<br>  <span class="hljs-comment">// configuration.getDefaultExecutorType() 获取了再全局配置文件settings中指定的执行器类型</span><br>  <span class="hljs-keyword">return</span> openSessionFromDataSource(configuration.getDefaultExecutorType(), <span class="hljs-keyword">null</span>, <span class="hljs-keyword">false</span>);<br>&#125;<br></code></pre></td></tr></table></figure></li>
<li><p>openSessionFromDataSource() 方法</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-function"><span class="hljs-keyword">private</span> SqlSession <span class="hljs-title">openSessionFromDataSource</span><span class="hljs-params">(ExecutorType execType, TransactionIsolationLevel level, <span class="hljs-keyword">boolean</span> autoCommit)</span> </span>&#123;<br>  Transaction tx = <span class="hljs-keyword">null</span>;<br>  <span class="hljs-keyword">try</span> &#123;<br>    <span class="hljs-comment">// 获取环境信息，创建事务工厂，创建事务 tx </span><br>    <span class="hljs-keyword">final</span> Environment environment = configuration.getEnvironment();<br>    <span class="hljs-keyword">final</span> TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);<br>    tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);<br>    <span class="hljs-comment">// 获取执行器  </span><br>    <span class="hljs-keyword">final</span> Executor executor = configuration.newExecutor(tx, execType);<br>    <span class="hljs-comment">// 返回 DefaultSqlSession</span><br>    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> DefaultSqlSession(configuration, executor, autoCommit);<br>  &#125; <span class="hljs-keyword">catch</span> (Exception e) &#123;<br>    closeTransaction(tx); <span class="hljs-comment">// may have fetched a connection so lets call close()</span><br>    <span class="hljs-keyword">throw</span> ExceptionFactory.wrapException(<span class="hljs-string">&quot;Error opening session.  Cause: &quot;</span> + e, e);<br>  &#125; <span class="hljs-keyword">finally</span> &#123;<br>    ErrorContext.instance().reset();<br>  &#125;<br>&#125;<br></code></pre></td></tr></table></figure></li>
<li><p>newExecutor() 方法</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-function"><span class="hljs-keyword">public</span> Executor <span class="hljs-title">newExecutor</span><span class="hljs-params">(Transaction transaction, ExecutorType executorType)</span> </span>&#123;<br>  executorType = executorType == <span class="hljs-keyword">null</span> ? defaultExecutorType : executorType;<br>  executorType = executorType == <span class="hljs-keyword">null</span> ? ExecutorType.SIMPLE : executorType;<br>  Executor executor;<br>  <span class="hljs-comment">// 通过不同的执行器类型创建不同的执行器  </span><br>  <span class="hljs-keyword">if</span> (ExecutorType.BATCH == executorType) &#123;<br>    executor = <span class="hljs-keyword">new</span> BatchExecutor(<span class="hljs-keyword">this</span>, transaction);<br>  &#125; <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (ExecutorType.REUSE == executorType) &#123;<br>    executor = <span class="hljs-keyword">new</span> ReuseExecutor(<span class="hljs-keyword">this</span>, transaction);<br>  &#125; <span class="hljs-keyword">else</span> &#123;<br>    executor = <span class="hljs-keyword">new</span> SimpleExecutor(<span class="hljs-keyword">this</span>, transaction);<br>  &#125;<br>  <span class="hljs-comment">// 如果开启了二级缓存，包装一下当前执行器  </span><br>  <span class="hljs-keyword">if</span> (cacheEnabled) &#123;<br>    executor = <span class="hljs-keyword">new</span> CachingExecutor(executor);<br>  &#125;<br>  <span class="hljs-comment">// 拦截器包装执行器  </span><br>  executor = (Executor) interceptorChain.pluginAll(executor);<br>  <span class="hljs-keyword">return</span> executor;<br>&#125;<br></code></pre></td></tr></table></figure></li>
</ol>
<h3 id="getMapper-获取代理对象"><a href="#getMapper-获取代理对象" class="headerlink" title="getMapper() 获取代理对象"></a>getMapper() 获取代理对象</h3><p><strong>工作流程：</strong></p>
<ol>
<li>调用 sqlSession 对象的 getMapper()，参数是 mapper 接口的 class 对象<ol>
<li>调用 sqlSession 内部 <code>Configuration</code> 对象的 getMapper() 方法<ol>
<li>调用 configuration 内部的 <code>MapperRegistry</code> 对象的 getMapper() 方法<ol>
<li>由于之前在创建 configuration 对象的时候，<strong>每一个 mapper 接口都有一个对应的 mapperProxyFactory 对象</strong>，现在通过 mapper 接口获取代理工厂类</li>
<li>调用 mapperProxyFactory 的 newInstance() 方法<ol>
<li>创建一个 <code>MapperProxy</code> 对象，该对象实现了 <code>InvocationHandler</code> 接口</li>
<li>通过 jdk 动态代理 Proxy.newProxyInstance() 创建代理对象并返回</li>
</ol>
</li>
</ol>
</li>
</ol>
</li>
</ol>
</li>
</ol>
<p><strong>时序图：</strong></p>
<p><img src="https://yechen-blog-image.oss-cn-hangzhou.aliyuncs.com/images/image-20211028145648462.png" srcset="/img/loading.gif" lazyload alt="getMapper() 获取代理对象时序图"></p>
<p><strong>代码摘要：</strong></p>
<ol>
<li><p>getMapper() 方法</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs java">StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Override</span><br><span class="hljs-keyword">public</span> &lt;T&gt; <span class="hljs-function">T <span class="hljs-title">getMapper</span><span class="hljs-params">(Class&lt;T&gt; type)</span> </span>&#123;<br>  <span class="hljs-keyword">return</span> configuration.getMapper(type, <span class="hljs-keyword">this</span>);<br>&#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> &lt;T&gt; <span class="hljs-function">T <span class="hljs-title">getMapper</span><span class="hljs-params">(Class&lt;T&gt; type, SqlSession sqlSession)</span> </span>&#123;<br>  <span class="hljs-keyword">return</span> mapperRegistry.getMapper(type, sqlSession);<br>&#125;<br></code></pre></td></tr></table></figure>

<p>MapperRegistry 类中的 getMapper() 方法</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> &lt;T&gt; <span class="hljs-function">T <span class="hljs-title">getMapper</span><span class="hljs-params">(Class&lt;T&gt; type, SqlSession sqlSession)</span> </span>&#123;<br>  <span class="hljs-comment">// 获取当前 mapper 接口对应的 mapperProxyFactory  </span><br>  <span class="hljs-keyword">final</span> MapperProxyFactory&lt;T&gt; mapperProxyFactory = (MapperProxyFactory&lt;T&gt;) knownMappers.get(type);<br>  <span class="hljs-keyword">if</span> (mapperProxyFactory == <span class="hljs-keyword">null</span>) &#123;<br>    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> BindingException(<span class="hljs-string">&quot;Type &quot;</span> + type + <span class="hljs-string">&quot; is not known to the MapperRegistry.&quot;</span>);<br>  &#125;<br>  <span class="hljs-keyword">try</span> &#123;<br>    <span class="hljs-comment">// 通过 mapperProxyFactory 创建代理对象  </span><br>    <span class="hljs-keyword">return</span> mapperProxyFactory.newInstance(sqlSession);<br>  &#125; <span class="hljs-keyword">catch</span> (Exception e) &#123;<br>    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> BindingException(<span class="hljs-string">&quot;Error getting mapper instance. Cause: &quot;</span> + e, e);<br>  &#125;<br>&#125;<br></code></pre></td></tr></table></figure></li>
<li><p>newInstance(sqlSession) 创建代理对象</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-function"><span class="hljs-keyword">public</span> T <span class="hljs-title">newInstance</span><span class="hljs-params">(SqlSession sqlSession)</span> </span>&#123;<br>  <span class="hljs-comment">// 创建 MapperProxy，是一个 InvocationHandler</span><br>  <span class="hljs-keyword">final</span> MapperProxy&lt;T&gt; mapperProxy = <span class="hljs-keyword">new</span> MapperProxy&lt;&gt;(sqlSession, mapperInterface, methodCache);<br>  <span class="hljs-keyword">return</span> newInstance(mapperProxy);<br>&#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-function"><span class="hljs-keyword">protected</span> T <span class="hljs-title">newInstance</span><span class="hljs-params">(MapperProxy&lt;T&gt; mapperProxy)</span> </span>&#123;<br>  <span class="hljs-comment">// 通过 jdk 动态代理创建当前接口的代理对象并返回  </span><br>  <span class="hljs-keyword">return</span> (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), <span class="hljs-keyword">new</span> Class[] &#123; mapperInterface &#125;, mapperProxy);<br>&#125;<br></code></pre></td></tr></table></figure></li>
</ol>
<h3 id="代理对象执行增删改查方法"><a href="#代理对象执行增删改查方法" class="headerlink" title="代理对象执行增删改查方法"></a>代理对象执行增删改查方法</h3><p><img src="https://yechen-blog-image.oss-cn-hangzhou.aliyuncs.com/images/image-20211028161936600.png" srcset="/img/loading.gif" lazyload alt="代理对象执行增删改查方法流程图"></p>

            </div>
            <hr>
            <div>
              <div class="post-metas mb-3">
                
                  <div class="post-meta mr-3">
                    <i class="iconfont icon-category"></i>
                    
                      <a class="hover-with-bg" href="/categories/SSM-%E6%A1%86%E6%9E%B6/">SSM 框架</a>
                    
                      <a class="hover-with-bg" href="/categories/SSM-%E6%A1%86%E6%9E%B6/MyBatis/">MyBatis</a>
                    
                  </div>
                
                
                  <div class="post-meta">
                    <i class="iconfont icon-tags"></i>
                    
                      <a class="hover-with-bg" href="/tags/SSM-%E6%A1%86%E6%9E%B6/">SSM 框架</a>
                    
                      <a class="hover-with-bg" href="/tags/MyBatis/">MyBatis</a>
                    
                  </div>
                
              </div>
              
                <p class="note note-warning">
                  
                    本博客所有文章除特别声明外，均采用 <a target="_blank" href="https://creativecommons.org/licenses/by-sa/4.0/deed.zh" rel="nofollow noopener noopener">CC BY-SA 4.0 协议</a> ，转载请注明出处！
                  
                </p>
              
              
                <div class="post-prevnext">
                  <article class="post-prev col-6">
                    
                    
                      <a href="/2023/03/06/%E5%A4%8D%E8%AF%95-%E5%A4%8D%E8%AF%95-C%E8%AF%AD%E8%A8%80%E5%AD%A6%E4%B9%A0/">
                        <i class="iconfont icon-arrowleft"></i>
                        <span class="hidden-mobile">考研复试-C语言学习</span>
                        <span class="visible-mobile">上一篇</span>
                      </a>
                    
                  </article>
                  <article class="post-next col-6">
                    
                    
                      <a href="/2021/10/09/SSM%E6%A1%86%E6%9E%B6-2021-10-09-SpringMVC%EF%BC%88%E5%B0%9A%E7%A1%85%E8%B0%B7%EF%BC%89/">
                        <span class="hidden-mobile">SpringMVC（尚硅谷）</span>
                        <span class="visible-mobile">下一篇</span>
                        <i class="iconfont icon-arrowright"></i>
                      </a>
                    
                  </article>
                </div>
              
            </div>

            
          </article>
        </div>
      </div>
    </div>
    
      <div class="d-none d-lg-block col-lg-2 toc-container" id="toc-ctn">
        <div id="toc">
  <p class="toc-header"><i class="iconfont icon-list"></i>&nbsp;目录</p>
  <div class="toc-body" id="toc-body"></div>
</div>

      </div>
    
  </div>
</div>

<!-- Custom -->


    

    
      <a id="scroll-top-button" href="#" role="button">
        <i class="iconfont icon-arrowup" aria-hidden="true"></i>
      </a>
    

    
      <div class="modal fade" id="modalSearch" tabindex="-1" role="dialog" aria-labelledby="ModalLabel"
     aria-hidden="true">
  <div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header text-center">
        <h4 class="modal-title w-100 font-weight-bold">搜索</h4>
        <button type="button" id="local-search-close" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body mx-3">
        <div class="md-form mb-5">
          <input type="text" id="local-search-input" class="form-control validate">
          <label data-error="x" data-success="v"
                 for="local-search-input">关键词</label>
        </div>
        <div class="list-group" id="local-search-result"></div>
      </div>
    </div>
  </div>
</div>
    

    
  </main>

  <footer class="text-center mt-5 py-3">
  <div class="footer-content">
     <a href="https://hexo.io" target="_blank" rel="nofollow noopener"><span>Hexo</span></a> <i class="iconfont icon-love"></i> <a href="https://github.com/fluid-dev/hexo-theme-fluid" target="_blank" rel="nofollow noopener"><span>Fluid</span></a> 
  </div>
  

  

  
</footer>


  <!-- SCRIPTS -->
  
  <script  src="https://cdn.jsdelivr.net/npm/nprogress@0.2.0/nprogress.min.js" ></script>
  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/nprogress@0.2.0/nprogress.min.css" />

  <script>
    NProgress.configure({"showSpinner":false,"trickleSpeed":100})
    NProgress.start()
    window.addEventListener('load', function() {
      NProgress.done();
    })
  </script>


<script  src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js" ></script>
<script  src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/js/bootstrap.min.js" ></script>
<script  src="/js/events.js" ></script>
<script  src="/js/plugins.js" ></script>

<!-- Plugins -->


  
    <script  src="/js/img-lazyload.js" ></script>
  



  



  <script  src="https://cdn.jsdelivr.net/npm/tocbot@4.12.3/dist/tocbot.min.js" ></script>



  <script  src="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.js" ></script>



  <script  src="https://cdn.jsdelivr.net/npm/anchor-js@4.3.1/anchor.min.js" ></script>



  <script defer src="https://cdn.jsdelivr.net/npm/clipboard@2.0.8/dist/clipboard.min.js" ></script>



  <script  src="/js/local-search.js" ></script>






  <script  src="https://cdn.jsdelivr.net/npm/typed.js@2.0.12/lib/typed.min.js" ></script>
  <script>
    (function (window, document) {
      var typing = Fluid.plugins.typing;
      var title = document.getElementById('subtitle').title;
      
      typing(title)
      
    })(window, document);
  </script>














  
<script src="//cdn.jsdelivr.net/gh/bynotes/texiao/source/js/xiaoxuehua.js"></script>
<script src="//cdn.jsdelivr.net/gh/bynotes/texiao/source/js/caidai.js"></script>
<script src="//cdn.jsdelivr.net/gh/bynotes/texiao/source/js/love.js"></script>
<script src="//cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.js"></script>
<script src="//cdn.jsdelivr.net/gh/metowolf/MetingJS@1.2/dist/Meting.min.js"></script>



<!-- 主题的启动项 保持在最底部 -->
<script  src="/js/boot.js" ></script>

  <!--动态线条背景-->
  <script type="text/javascript" color="70,119,184" opacity='1' zIndex="-2" count="200" src="//cdn.bootcss.com/canvas-nest.js/1.0.0/canvas-nest.min.js"></script>

<script src="/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"model":{"jsonPath":"/live2dw/assets/koharu.model.json"},"display":{"position":"left","width":200,"height":400},"mobile":{"show":false},"log":false,"pluginJsPath":"lib/","pluginModelPath":"assets/","pluginRootPath":"live2dw/","tagMode":false});</script></body>
</html>
